Swift code not called by obj-c with bridge header

Viewed 781

Issue:

I'm trying to build a bridge between Swift and Unity, in order to achieve that I need to create a bridge between Swift and Obj-C and call Obj-C code from Unity. I can now build and run the generated Unity Xcode project, and the Obj-C code can be called from Unity without an issue. But when I try to call Swift code from Obj-C, the Swift code doesn't seem to be ever called (I put a print("abc") in Swift code but nothing appears in the console).

What I did

Basically following this article, in short:

  1. Create a framework in Xcode, add a swift class and mark codes I wanted to expose to Obj-C as @obj public
  2. Under the framework add a .mm Obj-C file that calls Swift code, to achieve that it need to include the generated <MODULE_NAME>-Swift.h header file.
  3. Create a <PROJECT_NAME>-Bridging-Header.h to bridge the 2 code files.
  4. Compile the code, put the 3 files in Unity's iOS plugin folder (Assets/Plugin/iOS/<PROJECT_NAME>), add a c# script that calls the Obj-C code and a postprocess file to adjust Xcode settings when building the iOS project.
  5. Put the generated <PROJECT_NAME>.framework folder in Assets/StreamingAssets.
  6. Build the iOS project in Unity, open the Unity-iPhone.xcodeproj.
  7. Drag <PROJECT_NAME>.framework from /Data/Raw to /Frameworks, add it to the Unity-iPhone and UnityFramework target, changed the target membership for both to optional.
  8. Run the Unity-iPhone xcode project, Obj-C code can be called via Unity C# code, but the Swift code is not called.

My thoughts

In the Obj-C file it included a <MODULE_NAME>-Swift.h header file that describes the exposed Swift class functions, in theory that should be auto-generated by the Unity-iPhone project, but I have to drag the previously generated <PROJECT_NAME>.framework to the /Frameworks group in Unity-iPhone project for the Obj-C file to reference otherwise there will be a module not found issue. So there're actually 2 <MODULE_NAME>-Swift.h files in Unity-iPhone project, one in the <PROJECT_NAME>.framework and another one in UnityFramework.framework which is one of the products of the Unity-iPhone project. In Bridge.mm if I cmd+click on the reference to -Swift.h, it goes to the -Swift.h file in the framework in /Framework group. Then in the -Swift.h there's a definition of the Swift class like this:

...
SWIFT_CLASS("_TtC11<MODULE_NAME>12<CLASS_NAME>")
@interface CLASS_NAME : NSObject
...

If I cmd+click on the class, it refers me back to the actual swift class in the plugin, which is correct, but actually it's not calling the Swift code at all... Maybe the Obj-C is not calling the correct Swift code? Or it get confused? Maybe some build settings not set correctly in the postprocess? I'm not seeing any error from the console, the call just failed silently, any ideas on how to fix it?

1 Answers

Okay I finally figured it out, the generated header needs to be referenced by #import <UnityFramework/{TARGET_NAME}-Swift.h> instead of #import "{TARGET_NAME}-Swift.h", in this way it always reference to the generated Swift header file.

Related