Use XCFramework with objective C
Asked Answered
O

1

5

I have created one xcframework in Swift Language. I have marked by .swift class with @objc as well.

I tried to use <frameworkname-Swift.h> in objective c project, But it is showing Module not found error.

Can anyone help with how to use xcframework with Objective-C code.

Orford answered 8/1, 2021 at 7:11 Comment(1)
Have you use static or dynamic libraries to make xcframework?Poseidon
P
7

It's very important to make your libraries right before making xcframework and starting integrating them to your project.

Static libraries (.a)

Your class and its methods should be public and marked with @objc to be visible in Objc:

@objc public class SwiftHelloStatic : NSObject {
    
    @objc static public func hello() {
        print("Hello Static Library!")
    }
}

First add your "Objective-c Generated Interface Header" (e.g. SwiftHelloStatic-Swift.h) to "Build Phases > Copy Files", for instance from your destination or from DeviredData folder:

enter image description here

Build your needed arch (arm64/x86_64) and then you can find "include" folder in your library's one that contains your header:

enter image description here

Build your xcframework from libraries and headers:

xcodebuild -create-xcframework 
-library arm64/libSwiftHelloStatic.a -headers arm64/include 
-library x86_64/libSwiftHelloStatic.a -headers x86_64/include 
-output SwiftHelloStatic.xcframework

And after verify than your SwiftHelloStatic.xcframework has "Headers" folders inside arch ones:

enter image description here

Now just drag and drop your xcframework to "General > Frameworks, Libraries and Embedded Content" with "Do not Embed" because you have static libraries to link.

Last step to set "Build Settings > Header Search Path" to "<your_ destination>/SwiftHelloStatic.xcframework/**" to find your headers.

And finally you can add headers to your objc file:

#import <SwiftHelloStatic/SwiftHelloStatic-Swift.h>

...

[SwiftHelloStatic hello];

Dynamic framework (.framework)

It's similar to static libraries but simpler because frameworks already have headers. First set Build Library for Distrubution to YES and then build your framework for needed archs (arm64, x86_64, ...) and build you xcframework from them e.g.:

xcodebuild -create-xcframework 
-framework arm64/SwiftHello.framework 
-framework x86_64/SwiftHello.framework 
-output SwiftHello.xcframework

Now just drag and drop xcframework to "General > Frameworks, Libraries and Embedded Content" with "Embed & Sign".

In your objc project you should import your xcframework next way:

#import <SwiftHello/SwiftHello.h>

Thats because a valid xcframework contains separate dynamic frameworks for all its target platforms and a needed one from them is linked while compilation so that importing headers to your code is the same as for a regular framework.

Also verify that your classes are accessible in "SwiftHello-Swift.h" e.g.:

SWIFT_CLASS("_TtC10SwiftHello5Hello")
@interface Hello : NSObject
+ (void)hello;
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end
Poseidon answered 8/1, 2021 at 16:8 Comment(6)
I have tried it importing this way, But no success. I can see "FrameworkName-Swift.h" in DerivedSources under derivedData but when i create framework "ios-arm64" and "ios-x86_64-simulator" are visible which containts "library.a" and swiftModue files . I have tried placing ""FrameworkName-Swift.h"" manually but it also does not work. I used following commnad to create framework: xcodebuild -create-xcframework -library build/simulators/libTrackingManager -library build/devices/libTrackingManager -output build/TrackingManager.xcframeworkOrford
If you use .a files you should verify that .h headers are present in xcframework and try to set header search paths in your project settings.Poseidon
@Orford Please take a look my updated answer.Poseidon
@Poseidon do I need to mark objc only public classes? and what about public protocols and their methods?Deandre
@Poseidon and another question is, Do i need them mark objc if it's dynamic framework(.framework)?Deandre
@AlisherBaigazin You should mark @objc all entities classes, protocols, methods etc. that are needed for your public interface of the library.Poseidon

© 2022 - 2024 — McMap. All rights reserved.