Home > Mobile >  How to set up interoperability between internal Swift and Objective-C classes when developing a Fram
How to set up interoperability between internal Swift and Objective-C classes when developing a Fram

Time:08-29

I have a Framework with mixed Objective-C and Swift classes and i'd like to communicate between them keeping the Swift interface internal (without making Swift classes and methods public). Is there a way to achieve that?

P.S. Please pay attention that since it's a Framework project, it's not an option to use the bridging header solution, because it's not supported for frameworks.

CodePudding user response:

A solution, although hacky, is that you could mark the private swift methods with an Objective-C decorator @objc, and then call them from Objective-C using performSelector.

CodePudding user response:

Not sure what you mean by you can't use bridging header in framework project. You can't provide an arbitrary bridging header but Xcode does generate a bridging header with name {FrameWorkProjectName}.h. Note that in case of framework project, your objective c headers need to be public to be included in bridging header.

If you don't want to make your objective c headers public to use in swift, you have to create a module.map file at the root of your project and add all your internal/private headers:

module FrameWorkProjectName_Internal {
    // import your private headers here
    export *
}

and in your SWIFT_INCLUDE_PATHS build settings add $(SRCROOT)/FrameWorkProjectName so that this module is recognized by swift. To use any objective c code from the above module you have to import FrameWorkProjectName_Internal in your file (i.e. import FrameWorkProjectName_Internal).

To use swift types in your objective c you can mark your types/methods with @objc/@objcMembers and make them public so the generated header makes swift types available to your objective c files. Since you don't want to make your swift types public you can either use performSelector to send messages or you have to manually create header containing all your swift interface definition. For example, define type symbol name or selector name in your swift file with @objc attribute:

@objc(FrameWorkProjectName_SwiftType)
class SwiftType: NSObject {
    func call() { /* Do something */ }
}

and then define the swift type interface in your header file:

SWIFT_CLASS("FrameWorkProjectName_SwiftType")
@interface SwiftType : NSObject

- (void)call;

@end

When defining type symbol names make sure that it doesn't conflict with other names in your or any other external module. To avoid this try to include your framework name in symbol name.

  • Related