Convert a Swift library to NativeScript for Angular iOS apps

Nathan Walker
InstructorNathan Walker

Share this video with your friends

Send Tweet
Published 5 years ago
Updated 3 years ago

Swift is an exciting and intuitive programming language developed by Apple to be easier to learn than Objective C. It's syntax also more closely resembles JavaScript. Some native libraries you could work with may have been developed with Swift. Let’s look at a couple cases you could run into when trying to work with a Swift based iOS library. In particular, we will be implementing this Swift 3.0 CocoaPod. Also learn how to write files to your app’s document folder using NativeScript’s ‘file-system’ module.

[00:02] For example, SimplePDF, a library that was written in Swift, and if we look at the documentation on the ReadMe, we can see this example Swift code. Let's try to integrate this native Swift library.

[00:12] Let's grab the pod line for CocoaPod, and we'll create an internal plug-in for our project here. We'll call it NatveScriptPDF. We'll add our platforms iOS folder and our pod file, and drop our pod line. Then we'll create pdf.ios.typescript, and let's export a class called tns for telerik native script PDF.

[00:30] To check this out, let's create a static method that would call createPDF and tap into the Swift API. Let's take this code and convert it, and with the first line we just want to make sure we call new on this class.

[00:43] The Swift parameters that get passed into constructors, we want to convert to a standard object. Same with this line, we want to construct this class and convert these to an object. We'll just declare this for now.

[00:55] We'll add a package for our internal plug-in. We'll make sure we have a build script, and we'll make sure this runs the build and launches our app. Let's go ahead and build the plug-in, and now let's use it.

[01:11] In our app component, let's import that tnsPDF class from NativeScriptPDF. Let's add a method here that we can bind to our view, we'll call it createPDF. We'll call tnsPDFCreatPDF. In our view binding, let's just create a button. We'll say createPDF and we'll bind that to our createPDF method. Let's run this.

[01:31] You'll see we get a hard crash. If we take a look at the stack and what happened here, right at the very bottom of the build failure, we'll see that it mentions legacy Swift here. By default, Swift version 2.5 is still targeted. We want to make sure that this uses Swift 3.0If we refer back to the ReadMe we'll see that this is written in Swift 3.

[01:56] We can remedy this by adding a post-install hook onto our pod here, and this will reference the installer. We can call up the installer and call up podsproject.targets.e, and we'll loop through each target and we'll grab the build configurations and ensure that the config build settings sets the swift version equal to 3.0Now we want to install this fresh. For good measure, let's make sure our platforms folder is removed completely to make sure that when we run this again it will install that pod fresh and pull the new pod file.

[02:32] Now the app launches. Let's try to actually initiate this sequence with the Swift library and see what happens. You can see we get a hard crash, and it says can't find variable SimplePDF. This is the core class from the Swift library, and it is not available to NativeScript right now.

[02:51] In these cases, what we want to do is actually fork this library. We're going to make a few modifications. If we clone that project and have a look, we can find the source Swift file here, which defines the SimplePDF class.

[03:05] Right away we'll notice we need something here. What we need to do is expose this to Objective-C. We can add this @Objective-C modifier to the front of that class, and that will expose it.

[03:18] Then the other key thing we want to do is make sure that this class extends NSObject. With those two things in mind, we have now exposed this class. Now we want to commit those changes up to our fork. Now we can target that fork in our pod file by adding this get declaration to point to our forked repo.

[03:38] You could go ahead and submit a pull request back to the author, and get those changes in, but that is totally up to you. As we had done previously for good measure, we're going to remove the platforms folder again to make sure that it gets this new pod file and builds in our new fork.

[03:53] This time when the app launches and we choose Create PDF, we don't get that hard crash. So let's go ahead and build out our API since we know that that class is now available.

[04:04] Back to the example Swift code, we'll just for now for simplicity implement this addText method and we'll add some text here. Then let's go ahead and try to write a PDF to a file and see if we can get this to work.

[04:18] We can see this generatePDFData method is going to hand us back some data, but we don't know what datatype this is. We get a little bit of a hint by looking at this writeToFile. Let's take a look at the source, and let's look for that method. Here it is, and we can see it actually returns a datatype called data.

[04:35] If we go to Apple's API reference documentation, we'll see mentioned that the Swift overlay to the foundation framework provides the data structure which bridges to the NSData class. We know that it is a representation of the NSData class. If we look down at the method signatures, we'll see this writeToFile:atomically. There's also writeTo:atomically, and writeToFile options.

[05:01] We can see this is using writeToFile options, but since this is NSData, we can use any of these methods, actually. For this example we'll just use this writeToFile:atomically, since it's simple, and we can pass a path to a file.

[05:17] To be consistent, we can wrap this in a try and catch block. To convert this, since we're going to use the writeToFile:atomically method, we'll add atomically to the end. Then we can get rid of this option here, and we're just going to pass TRUE, since atomically takes a Boolean.

[05:35] Then we need a file path. We can import NativeScript's file system module to help us out. Let's first get a reference to the documents folder for the app. It's worth noting that in production you cannot write a file to your local app directory, you would have to write a file to the documents directory for security reasons.

[05:58] We're going to use the path API to join the documents path with a new file we'll just call test.pdf. That will give us the path to write to. Just so we can see it, let's actually log out that full path. Let's give it a shot.

[06:14] Now when the app launches and we tap Create PDF, we can see that it actually did log that it wrote a PDF to this location. We can take this path, and we'll open it to see what we got. We have a full-blown PDF written to file with the text that we added using the Swift API.