Toll Free: +1-855-656-NUVI

Using Native Libraries in Your NativeScript Apps

Using Native Libraries in Your NativeScript Apps
  • Share:
When developing a NativeScript app, you might run into a situation where you really need to use a native library that’s you’ve already written, or a library that someone else has already made available as an open source project, for example. Should you rewrite that library or framework in JavaScript or create a new NativeScript module? Well, you certainly could do that, but the good news is that you don’t have to. NativeScript has this neat little feature that allows you to import an existing native library and call it from your NativeScript app. This post will show you how you can use a native iOS library in your own app.

 

Versions used in this post 
  • NativeScript: 0.9.4
  • Xcode 6

 

Update May 12, 2015

I've updated the companion code in the GitHub repo for NativeScript version 1.0.1 and included the lib folder for those who just want to download and try out the app right away.

 

Yes, you read that right.

You can call your native objects with JavaScript.

 

Not only can you do this for the standard frameworks that come with iOS and Android, but you can use your own as well. I will show you how to build and configure the framework for iOS using Xcode and how to import and call the library form your NativeScript app. There are a few things that could trip you up and I will make a note of these items in the appropriate sections.

I’ve prepared a sample for you that you can download from GitHub and try out for yourself. The sample Xcode library is a temperature converter that converts between Celsius and Fahrenheit and vice versa. The steps below will refer to this sample, so if you download it you’ll be able to follow along easier. Here is the sample.

 

Preparing Your Own Xcode Library

Let’s say you already have an existing code base that you wrote and you want to reuse it in your NativeScript app. In the sample that I provided, there is an Xcode project that is set up correctly. All this sample does is convert Celsius and Fahrenheit temperatures. Here is what the header code looks like to give you an idea. Ns_Native_iOS_Libs_1

  1. The project should be created as a dynamic framework – this is currently the only type of library that is supported.
    In Xcode, File->New->Project Ns_Native_iOS_Libs_2
  2. Classes you want to use in NativeScript should be exposed publicly. I’ve opened the TemperatureConverterFramework project in Xcode
    • The main framework header file called TemperatureConverterFramework.h should #import the headers that you want accessible in your app so the NativeScript metadata generator can find them. In this case, the only class is imported is TemperatureConverter.h Ns_Native_iOS_Libs_3

    • The header files that you want public should also be exposed in the project Build Phases properties. I wanted TemperatureConverter.h to be available to my NativeScript app, so I moved it from the Project list to the Public list under the Headers section. Ns_Native_iOS_Libs_4

  3. When building the project, make sure to follow the tips below, or you’ll be in for a trick instead of a treat.

    Remember that when building for a device, select the generic iOS Device as the target, build, and then import from the iphoneos directory (more on that later). When building for the iOS simulator, select a simulator as the target, build, and then import from the iphonesimualtor directory.

    • Gotcha 1 - Build the Xcode Framework project with your device physically disconnected from the Mac. I’ve lost a couple of hairs figuring this one out. When I build with my iPhone connected, there are problems with finding the library variables when running the app. When I disconnect my device from the Mac and build the project for a generic iOS Device, everything works well. This is the target menu when selecting what device to build for:

      Ns_Native_iOS_Libs_5
    • Gotcha 2 - If you’re going to run the app on the iOS simulator, you have to build the project in Xcode for the simulator, and then you have to import the simulator library into your NativeScript app. See the Importing section later.

      Ns_Native_iOS_Libs_6

 

Utilizing an Existing Xcode Library or Framework

Another scenario is you found a cool library that someone else has written and you want to use it in your app.

  • Verify that the library was created as a dynamic framework, also known as a Cocoa Touch Framework.

  • If the library was not created as a Framework, there are two things you can do if you have the source code:

    • You can attempt to change the framework type in the project properties – but I’ve found this to be a fragile approach that could lead to further build errors.

    • Create a separate Cocoa Touch Framework project and copy and paste the classes into the new project from the old project.

    Note: For an example of using an existing iOS library in your NativeScript app, see my post on using NativeScript with Azure Mobile Services part 2.

  • If you don’t have the source code and the library is of a static type, then at this time you won’t be able to use it. But perhaps the NativeScript team will work on a way to get these types of libraries working in the future.

 

Importing and Using the Framework in Your App

Once the library (or framework) has been built properly and is the correct project type, you can import it into your NativeScript app and use it. The sample download includes a demo NativeScript app that uses the TemperatureConverter library. Familiarity with creating and running NativeScript apps with the CLI is assumed, but if you need a refresher, start here.

  1. If you haven’t done this already or you want a clean slate, add the iOS platform to your NativeScript project.

    tns platform add ios
    
  2. Assuming you’ve built the project correctly (see steps above), you can now add the TemperatureConverterFramework iOS library to your project. Your path might be slightly different due to the randomly generated directory for he product build.

    • If building for a device, add the library from the Debug-iphoneos subdirectory

      tns library add ios /Users/alex//Library/Developer/Xcode/DerivedData/TemperatureConverterFramework-hiimmywwmpyjhselvsqcximsvgic/Build/Products/Debug-iphoneos/TemperatureConverterFramework.framework
    • If building for the simulator, add the library from the Debug-iphonesimulator subdirectory

      tns library add ios /Users/alex//Library/Developer/Xcode/DerivedData/TemperatureConverterFramework-hiimmywwmpyjhselvsqcximsvgic/Build/Products/Debug-iphonesimulator/TemperatureConverterFramework.framework
  3. You will be able to refer to your class in your NativeScript JavaScript code. The included sample utilizes the static members of the class to convert temperatures, but you can just as well new up the object and use the instance members. The highlighted line shows a call to the TemperatureConvert class in the iOS library that was imported.

    mainViewModel.tapFtoC = function () {
        var tempVal = getTempFieldValue();
        var newTempVal = TemperatureConverter.fahrenheitToCelsius(tempVal);
        mainViewModel.set("result", newTempVal);
    };
    
  4. Run the app on your device and you will have a functioning app that converts temperatures.

    Ns_Native_iOS_Libs_7

 

Summary

As you can see, there are a few gotchas here that can potentially trip you up, but if you follow the steps outlined in this post, you should be fine. Have fun using your libraries. Remember that NativeScript is still pre-release, so if something isn’t working and it should, take a step back and remove the iOS platform folder and the library folder, add them back in, and try again – your problem might be fixed.

Alexander Ziskind
Alexander Ziskind

From the latest tech in web development to the latest electronic music hardware and software, Alex loves to get his hands on new stuff and hack on it. Follow this feed on Nuvious related news; so web and cloud stuff here.

2 Comments

Jessie
May 12, 2015 Jessie

This is not working, at least not with the latest NativeScript version. I got the files from GitHub, followed all the steps, and got the error below. I also deleted the "ios" platform directory and the "lib" directory before trying again.

ession started without errors.
/app/main-view-model.js:17:42: JS ERROR ReferenceError: Can't find variable: TemperatureConverter
1 0x66be2 NativeScript::FFICallback<NativeScript::ObjCMethodCallback>::ffiClosureCallback(ffi_cif*, void*, void**, void*)
2 0x5888d6 ffi_closure_SYSV_inner
3 0x588322 .LCFI7
4 0x22667cd -[NSObject performSelector:withObject:withObject:]
5 0x1074a90 -[UIApplication sendAction:to:from:forEvent:]
6 0x1074a22 -[UIApplication sendAction:toTarget:fromSender:forEvent:]
7 0x11b518a -[UIControl sendAction:to:forEvent:]
8 0x11b55a7 -[UIControl _sendActionsForEvents:withEvent:]
9 0x11b4811 -[UIControl touchesEnded:withEvent:]
10 0x10cccfa -[UIWindow _sendTouchesForEvent:]
11 0x10cd7d6 -[UIWindow sendEvent:]
12 0x108b6d1 -[UIApplication sendEvent:]
13 0x109bb08 _UIApplicationHandleEventFromQueueEvent
14 0x106f337 _UIApplicationHandleEventQueue
15 0x28c806f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
16 0x28bdb7d __CFRunLoopDoSources0
17 0x28bd0d8 __CFRunLoopRun
18 0x28bca5b CFRunLoopRunSpecific
19 0x28bc88b CFRunLoopRunInMode
20 0x42ca2c9 GSEventRunModal
21 0x42ca106 GSEventRun
22 0x1073106 UIApplicationMain
23 0x58823d .LCFI1
24 0x58881f ffi_call
25 0x7b46a NativeScript::FFICall::executeFFICall(JSC::ExecState*, void (*)())
26 0x7b3e1 NativeScript::FFIFunctionCall::executeCall(JSC::ExecState*)
27 0x3f733f JSC::LLInt::setUpCall(JSC::ExecState*, JSC::Instruction*, JSC::CodeSpecializationKind, JSC::JSValue, JSC::LLIntCallLinkInfo*)
28 0x3f31e6 llint_slow_path_call
29 0x3fce16 llint_entry
30 0x3fce26 llint_entry
31 0x3fce26 llint_entry
Session ended without errors.

Alexander Ziskind
May 12, 2015 Alexander Ziskind

There are a few things that changed in NativeScript since the version this post originally used. The current version is 1.0.1. I've updated the GitHub companion demo to the latest version and tested the Temperature Converter app with the iOS Framework. All works now. Thanks for your comment.

Leave your comment