Search code examples
c#ios.netmaui.net-8.0

How to use iOS .framework files in .NET 8.0 MAUI


Can someone please create a binding library that uses .framework and NOT ".a" static lib along with working MAUI demo that uses the binding library so we can close this issue and get it over with?


Solution

  • Step 1:

    Create a folder structure like this:

    App/ (.NET 8.0, MAUI)
    │   App.csproj
    │   ...
    App.Binding/ (iOS/MacCatalyst Binding Library)
    │   ApiDefinition.cs
    │   App.Binding.csproj
    │   StructsAndEnums.cs
    App.Frameworks/ (created by hand)
    └───FAT
    └───Frameworks
    

    Step 2:

    Copy the .framework(s) into the App.Frameworks/FAT/ and App.Frameworks/Frameworks/ directory

    Step 3:

    Generate a FAT framework from the frameworks. Note that you can add more than one framework into the FAT framework, as long as they are targeting different architectures

    lipo -create -output App.Frameworks/FAT/[Name].framework/[Name] App.Frameworks/Frameworks/[Name].framework/[Name] ...
    

    Step 4:

    Use Sharpie to generate the ApiDefinition.cs and StructsAndEnums.cs.

    Notes:

    1. You might need to run this command with elevated permissions (e. g. sudo) if you are using Apple frameworks as imports
    2. You might need to change the paths of the imports in the header files to relative paths, e. g. #import <MyFramework/MyFrameworkExt.h> to #import "MyFrameworkExt.h" (in this case both headers would be in the same directory)
    3. This example is for iOS, but should be similar for MacCatalyst
    sharpie bind --sdk=iphoneos16.2 --output="ApiDefinition" --namespace="App.Binding" --scope="App.Frameworks/FAT/[Name].framework/Headers/" "App.Frameworks/FAT/[Name].framework/Headers/[Name].h"
    

    Step 5:

    Copy the parts of the newly generated files, found in the directory ApiDefinitions, which you will need for your bindings into the following files:

    • App.Binding/ApiDefinition.cs
    • App.Binding/EnumsAndStructs.cs

    Step 6:

    Remove any [Verify] attribute from the files in the binding, since they will be causing errors and remove the using directive at the very top of the App.Bindings/ApiDefinition.cs file, which refers to the framework you are linking

    Step 7:

    Notes:

    1. If you are using MacCatalyst you need to modify the location paths in the linker flags
    2. Check which frameworks you are using in the <Frameworks> tag and change them to your needs

    Update your App.Binding/App.Binding.csproj by adding the following:

    <ItemGroup>
        <NativeReference Include="..\Frameworks\FAT\[Name].framework">
            <Kind>Framework</Kind>
            <Frameworks>Foundation UIKit [Name]</Frameworks>
            <LinkerFlags>-L "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator/" -L "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos" -Wl,-rpath -Wl,@executable_path/Frameworks</LinkerFlags>
        </NativeReference>
    </ItemGroup>
    

    Step 8:

    Update your App/App.csproj file to load the binding project.

    Notes:

    1. You might consider adding a conditional loading of the reference
    2. Even though you are linking the project reference, some IDEs require to build the binding by hand and then unload the binding project in order to display code completion and accept the using directive in other files
    <ItemGroup>
        <ProjectReference Include="..\App.Binding\App.Binding.csproj"/>
    </ItemGroup>
    

    Hopefully this will help you and I did not miss out on any step. If you have any questions, just let me know!

    BR, Niko