How to use Obj-C Framework code in Swift Framework? - ios

How to use Obj-C Framework code in Swift Framework?
Is it possible or I need to mix them in a single Framework?
I have code for both Frameworks. I connect them manually without CocoaPods, Carthage or Swift Package Manager. Bridging header cannot be used inside of a Framework, only in App Target. Google says that I need to use modulemap file. In all examples I found they create their own modulemap files and put them near the Swift framework code. I tried to use both my own modulemap file and existing one inside ObjCFramework.framework/Modules. I use them by adding a path to the modulemap file to SWIFT_INCLUDE_PATHS build setting of my Swift Framework. I also tried to #import Obj-C Frameworks Ubrella Header to Swift Frameworks Ubrella Header with no luck. Of course I added the Obj-C Framework target to my Swift Framework target dependencies, the framework itself to Frameworks and Libraries and the path to it to Framework Search Paths. I didn't put anything to Header Search Paths to avoid "Include of non-modular header inside framework module", but that didn't help. CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES build setting doesn't help too. DEFINES_MODULE is set to YES.
Now I'm in endless loop of several errors:
Include of non-modular header inside framework module 'ObjCFramework': '/Users/bond/Library/Developer/Xcode/DerivedData/SwiftFramework-aqidpocynynsvdgtrqwukanwqkxf/Build/Products/Debug-iphoneos/ObjCFramework.framework/Headers/View.h'
Module 'ObjCFramework' was built in directory '/Users/bond/Library/Developer/Xcode/DerivedData/SwiftFramework-aqidpocynynsvdgtrqwukanwqkxf/Build/Products/Debug-iphoneos/ObjCFramework.framework' but now resides in directory '/Users/bond/Library/Developer/Xcode/DerivedData/SwiftFramework-aqidpocynynsvdgtrqwukanwqkxf/Build/Products/Debug-iphoneos/ObjCFramework.framework/Modules'
No such module ObjCFramework
underlying Objective-C module not found

In brief this is described here: https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_objective-c_into_swift, "Import Code Within a Framework Target" chapter.
If the Defines Module setting is turned on in your framework target, modern Xcode puts Modules folder in the framework, with Swift versions of all you ObjC public interfaces, making ObjC stuff available either for external Swift code that links your framework or Swift code of the framework itself.
This does not depend on whether your framework target contains any swift code.
Just add you ObjC header to framework target, mark it as Public in "Target membership", include in framework Umbrella header and build.

Related

iOS Swift framework from ObjC framework without modulemap

I'm working on Swift framework implementation and trying to use the closed source Objective-C framework (let us call it 'InternalObjectiveC.framework') provided by vendor
in Swift framework( let us call it 'ExternalSwift.framework').
The problem:
The 'InternalObjectiveC.framework' doesn't have modulemap or SwiftModule.
When I try to use the Objective-C classes (declared in 'InternalObjectiveC.framework') from Swift code (of 'ExternalSwift.framework') the Xcode cannot find them
I've tried to use Bridging Header, but faced with issue
"error: using bridging headers with framework targets is unsupported"
Also I've tried to make umbrella framework to expose the headers - it works.
My question is:
Is there a better way to make interoperability between Swift framework and the Objective-C framework(which doesn't have modulemap)?
Already checked other answers:
iOS mixed dynamic framework - bridge objc headers with private module,
Embedded Frameworks in Swift/iOS: Cocoapods-Packager dependency ModuleMap error (.modulemap' not found / underlying Objective-C module not found),
Objective-C Bridging Header for frameworks
In my case, i didn't need 'InternalObjectiveC.framework' modulemap. But i created modulemap for Swift framework. Something like this:
module InternalObjectiveC {
header "Pods/InternalObjectiveC/InternalObjectiveC.framework/Headers/InternalObjectiveC.h"
export *
}
Then in Build Settings, i searched for 'Import Path' and provide it new module.modulemap path. For example '$(SDKROOT)/ProjectModule'
Then i was able to compile all the things,
Hope this help.

How to create a framework with Objectivec files and Swift files

I have a Xcode project with Obiective-c files and swift files, Now i want to create a framework with both classes, Is this possible ?
Yes, this is straightforward and the process is documented by Apple. Please read "Swift and Objective-C in the Same Project" with thought and you'll be wiser (the section "Importing Code from Within the Same Framework Target" covers importing Objective-C in Swift from the same target, and the other way). Briefly…
For framework targets you don't need to create a bridging header to make your Objective-C importable to Swift, you just need to #import those headers you want visible to Swift in the framework's umbrella header. For that to work, the header needs to be marked public.
For Swift to be importable in Objective-C in the same framework target, make sure "Defines Module" is toggled on for the target, and in the files where you need to reference the Swift types, do an import in the style #import <ProductName/ProductModuleName-Swift.h>. If I recall this right, the Swift types / methods / properties you want to access from Objective-C will need to have been declared public for it to be accessible to Objective-C code even if it's in the same target.

How to call Objective-C libraries in dynamic framework Swift?

I have created a dynamic framework with Swift language. In this framework I am using mailcore2-ios that was build by Objective-C code. So how can I use it in swift file of my framework?
I try "public" and add a header .h file to umbrella but it still not work, have so much error for other header file as the image what I attach.
Xcode does not allow the use of bridging headers in framework targets. You should use the methods described here : http://iosdeveloperzone.com/2014/10/03/using-commoncrypto-in-swift/

Adding Objective C framework inside Swift Framework

I am writing a Cocoa Framework for iOS in Swift language. I need to add a third party framework (written in Objective-C) inside this framework. I have added headers to the bridging file. But when i build the project i get the following error:
"using bridging headers with framework targets is unsupported"
You should use import ObjcFrameworkName instead of using bridging header.
To make this possible objc framework must contain .modulemap file with exported module name and umbrella header for all public headers of this framework.

Building a Swift framework with references to Objective-C code

I'm working on an iOS project written in Swift, and I would like to take some classes out of the regular "app" project, and bundle it into a reusable Swift framework instead (and maybe make it publicly available on Github and via Cocoapods).
I'm running into issues because frameworks seemingly can't have Objective-C bridging headers, but in order to compile my framework code, I need to reference several Objective-C classes (in this case: the Google Maps iOS SDK).
I've also added GoogleMaps.framework as a linked library in my framework project, but then, how can I "import" it from Swift code?
Is this even possible with the current tools and Swift version, and how should I proceed?
Thanks.
It wasn't that complicated, actually... I was just doing some things wrong.
First, bridging headers are not required in that setting: the Google Maps iOS SDK is provided as a regular .framework file, so the development language has no impact on how it can be imported in Swift. Apple clearly mentions it in the documentation: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html, "Importing external frameworks".
It's as easy as adding the framework to the "Link binary with libraries" section of the project settings. Do not forget to also add depending libraries and frameworks (in GoogleMaps.framework's case, there are quite a few).
Then, in Swift code, the framework classes should be available simply by doing:
import GoogleMaps
No bridging header, no dealing with "non-modular header etc." errors.

Resources