Search code examples
cocoapodsnativescript

NativeScript: CocoaPod that works in Pod example does not expose symbols in plugin project


I am trying to understand the best ways in which to bring native library code into a NativeScript plugin for iOS. I've had success in past bringing in a CocoaPod and accessing the symbols from that. So I want to create my own. I follow the process for pod lib create TestPod to generate my library project. (https://guides.cocoapods.org/making/using-pod-lib-create.html) The 'library' is a trivial test: it simply creates a class with a function that returns a recognizable greeting string. The associated "Example app" demo produces a text label that displays this string.

This all works as expected, all running in pure iOS world (written in Swift).

At the Nativescript side, I'm using the Nativescript Plugin Seed and I'm declaring my Podfile in the src/platforms/iOS folder as directed. My "plugin" (trivial as it is as a test), has the iOS-specific parts in the pluginName.ios.js file. I have a separate test method in here that verifies I can reach and use native iOS platform symbols (e.g. NSMutableString) and that works as expected. I want to do the same thing with native code imported from my library.

But when I bring the Podfile into Nativescript, it builds okay, but I'm not able to see any of the symbols as I would expect to see. I generate typings and I don't find them either, but I do find a "TestPod.d.ts" typings file that declares some version info and a mysterious class named "UITest" that I did not define and bears no resemblance to my "SimpleTest" class, which I can't find anywhere.

I'm sure I'm missing something here that is probably obvious to the knowledgeable. But I'm unable to guess what it is. Any ideas?

import Foundation 
@objc public class SimpleTest : NSObject { 
  public func announce() -> String { 
     return "Greetings from Swift code in a library" 
  } 
}

I'm calling it in the plugin using the following:

    public testNativeLib() : string {
        let str:string;
        try {
            const testClass = new SimpleTest()
            str = testClass.announce()
        } catch(e) {
            str = e.message;
        }
        return str;
    }

and what I get returned for str is the catch case error message: "Can't find variable: SimpleTest"


Solution

  • Without seeing the source to the pod file; the only guess would be that you didn't use the @objc on anything that you wanted exposed. Without you exposing anything with @objc (or descending from a native objc class, so it is tagged by swift automagically) NativeScript cannot see it.

    Please note their are some types in Swift that currently cannot be consumed by NativeScript (Or ObjC) and you have to write some wrapper code in swift around it using types that are compatible with ObjC so that NativeScript can use it.

    Please see: https://docs.nativescript.org/guides/ios-source-code for more info on requirements...

    The code needs to be:

    import Foundation 
    public class SimpleTest : NSObject { 
       @objc public func announce() -> String { 
           return "Greetings from Swift code in a library" 
       } 
    }
    

    Move the @objc to the actual property/function you want exposed. The NSObject will already cause the class to be exposed if it has exposed members.

    The metadata generated:

    enter image description here


    A complete demo using a swift source file in a plugin is now located at

    If I have full control over the source, then I won't normally add another moving piece (i.e. cocoapod) to the mix; just let xcode compile the swift code and expose it, no need to add any additional places something can break.

    However, if you want to see how to do an actual swift CocoaPod plugin; checkout any of these plugin repos that use swift code and cocoapod:

    In the case of an actual cocoapod; you need to have a valid Podfile, and a valid podspec file! Once you have those; when you build the application, you can open up xcode and verify that the cocoapod is linked in. If it isn't linked in then your podfile/podspec is messed up and has to do with a issue with Cocoapod and it is not a NativeScript issue. So in that case; you need to follow some Cocoapod tutorials to get it to work.

    Please note; nuking your platform folder frequently while you are testing with cocoapods is highly recommended. Occasionally Nativescript does not detect the changes to Native code properly and so it then doesn't rebuild the xcode project/workspace files. So nuking your platforms folder will of course force it to rebuild them. If you don't you WILL waste a lot of time while messing around with cocoapods.

    When running the sample project you will see this: enter image description here

    In addition, in the demo, the metadata generated from the code I saved in the demo/metadata folder so you can look at it.