Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. We are looking for feedback on the experimental Unity Safe Mode which is aiming to help you resolve compilation errors faster during project startup.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Swift iOS native plugins hurdles

Discussion in '2019.3 Beta' started by z000z, Jan 2, 2020.

  1. z000z

    z000z

    Joined:
    Dec 31, 2014
    Posts:
    90
    With the iOS change to making all the Unity code now be in the UnityFramework target it's added some new hurdles for using swift to write a plugin to expose iOS functionality to the c# side.

    Previously you could create a bridging header to bridge swift and objective-c/c++ so that you can have your swift code and then c wrapper to expose to c#. Unfortunately frameworks are not allowed to have bridging headers.

    Mixing Swift and Objective-C/C/C++ code in a Framework requires you to have any code that the Swift code needs access to in the Public Headers section of the build target. So for Swift code to access the Unity "SendMessage" function you need access to the UnityInterface.h. So ideally you'd add UnityInterface.h to the headers and then be done, except that you can't because UnityInterface isn't a header that is allowed in the headers section.

    This is solvable though you can build an objective-c wrapper class for UnityInterface.h's SendMessage and then include your objective-c classes header in the headers section. And then also include it in the UnityFramework.h umbrella header. Also strangely you may need to re-order the build phases so that the the headers build phase is first for everything to work.

    So while you can get swift plugins to work with some manual manipulation of the Xcode project, these manual steps as far as I can tell are not available in the PBXProject class.

    It seems like at least some of that is "almost" part of the PBXProject class, I can locate the header I need using FindFileGuidByProjectPath, and it seems like AddFileToBuildSection ought to work if you give it the write guid for the header section, but interestingly if I copy the guid out of the pbxproject used for that section and use it it AddFileToBuildSection crashes. Also oddly calling GetBuildPhaseName on that guid causes a null reference, which is odd considering GetAllBuildPhasesForTarget does return that guid in it's array.

    But even if that did work there's no good way to re-order the build phases as far as I can see, and add your wrapper header to the UnityFramework.h.

    I think ideally UnityInterface.h would be made compatible or some equivalent compatible header would be in the headers section already and possibly the headers would be at the top of the build phases by default.
     
    cloutiertyler and liamwalsh like this.
  2. n8zach

    n8zach

    Joined:
    Jan 15, 2020
    Posts:
    1
    I think I have a very similar issue... I am trying to enable adding the TestFairy SDK to my Unity project and build in Unity Cloud Build. It requires configuring a bridging header as described here https://docs.testfairy.com/iOS_SDK/Integrating_iOS_SDK.html#ios-swift but I cannot figure out how to script this as a post export step using the PBXProject API.
     
    Wixar172 likes this.
  3. Krusty666

    Krusty666

    Joined:
    Feb 24, 2020
    Posts:
    5
    @n8zach I think your problem is easy to solve. You just need the Bridging header and then include it in your Plugins/iOS folder in Unity no PBX needed.
     
  4. Krusty666

    Krusty666

    Joined:
    Feb 24, 2020
    Posts:
    5
    Hi zOOOz,
    could you elaborate how mixing Objective-C and Swift with the UnityFramework target? I have exactly the same problem and and find out how to achieve this. I tried everything Google had to offer but without success.
    The manual steps you are referring to would be enough for now. When it works I would drive deeper into the PBX-Stuff.
     
  5. z000z

    z000z

    Joined:
    Dec 31, 2014
    Posts:
    90
    @Krusty666 Sure, there's a few steps we have to do:
    1. In your c interface .mm file you'll need to change your include from "projectname-swift.h" to
    #include "UnityFramework/UnityFramework-Swift.h"
    2. If you're using SendMessage in your swift code, you'll have to write an objective-c wrapper class, that you call SendMessage from, and then use your wrapper class in your swift code. Since you can't include the UnityInterface.h file in the swift code.

    Then if you do write that wrapper class, you'll have to do a few more steps for it to work:
    1. In the Xcode project go to Build Phases, select the UnityFramework Target, and then Drag the Headers section to the right under dependencies.
    2. Add your wrapper objective-c header to the Headers section, and then drag to public.
    3. Modify the UnityFramework.h to import your wrapper objective-c header, right above the UnityAppController import

    That should hopefully get you going.
     
    cloutiertyler likes this.
  6. aasiq

    aasiq

    Joined:
    Dec 29, 2016
    Posts:
    8
    @z000z, I've tried your steps. I can incluce Unityframework.h in .mm file. But, it doesn't contains headers for my swift code. So, it throws error like this.
    upload_2020-7-16_12-33-40.png
     

    Attached Files:

  7. naninunenoy

    naninunenoy

    Joined:
    Oct 25, 2017
    Posts:
    1
    @aasiq I had same issue. You need to make public your swift class to use in obj-c.
     
  8. cloutiertyler

    cloutiertyler

    Joined:
    May 12, 2018
    Posts:
    5
    > 1. In your c interface .mm file you'll need to change your include from "projectname-swift.h" to
    #include "UnityFramework/UnityFramework-Swift.h"

    Sweet heavens @z000z you saved my life with this.
     
unityunity