iOS8: Custom Swift Framework accessing external framework written in Objective-C
Asked Answered
G

3

8

I'm trying to create a custom framework called CouchbaseKit (a new target in Xcode) in Swift. Inside my CouchbaseKit, I need to access CouchBaseLite Framework that's entirely written in Obj-C. I'm using Cocoapods to manage CouchBaseLite and a couple of other frameworks. Below is my podfile.

Podfile

# Uncomment this line to define a global platform for your project
link_with ['CouchbaseKit']
# platform :ios, '8.0'

use_frameworks!
target 'CouchbaseDB' do
link_with ['CouchbaseKit']

pod 'couchbase-lite-ios'
pod 'SwiftyJSON', '~> 2.2.0'
pod 'Alamofire', '~> 1.2'
pod 'XCGLogger', '~> 2.0'
end

target 'CouchbaseDBTests' do
end

target 'CouchbaseKit' do
end

target 'CouchbaseKitTests' do
end

Pods inside the project:

enter image description here

For my TARGETS I have the following settings in Build Phases.

Define Module Yes

Allow Non-modular Includes in Framework Modules Yes

Problem: When I try to access the CouchbaseLite framework inside my CouchbaseKit (my custom framework), I get an error, "No such module 'CouchbaseLite' does not exist.

enter image description here

Tried:

  1. Since the project is in Swift, I created an Objective-C File and Hit yes to "Would you like to configure an Objective-C bridging header?"

  2. Even though Allow Non-modular Includes in Framework Modules is set to YES in all targets, I still get an error when I try to #import <CouchbaseLite/CouchbaseLite.h> in CouchbaseKit.h enter image description here

Here is what my Build Phases looks like for my custom framework CouchbaseKit

enter image description here

Question: How can I see an external Objective-C framework (CouchasebaseLite) in my custom Swift framework?

Grogram answered 28/7, 2015 at 22:41 Comment(1)
Try having a look at this repo to see if you can get any clues from it.Dyspnea
R
2

Unfortunately Cocoapods 0.39 suffers from "Transitive Vendor Dynamic Libraries Unsupported" You'll see this with the newest couchbase-lite-ios release including the binary CouchbaseLite.framework. This unfortunately issue bit me so hard I had to refactor everything to use Carthage, and manually manage my frameworks in my final projects.

Speaking of which the binary released CouchbaseLite.framework is simply missing a module map.

Add one to: CouchbaseLite.framework/Modules/module.modulemap

framework module CouchbaseLite {
  umbrella header "CouchbaseLite.h"

  export *
  module * { export * }
}

You will then be able to include this framework into a bridging header, and have your dynamic framework nest properly. But you might need to switch to building your CouchbaseKit.framework to using Carthage like I did.

Ranchero answered 19/10, 2015 at 6:58 Comment(3)
@Jens-Alfke I've noticed you mention it's available by default in swift global namespace in other comments, however I found it not appearing there, instead I had to add it to the bridging header and due to the missing modulemap you get a "No such module" error. This is in Xcode 7.1 beta 4, so maybe on prior Xcode releases you could be correct.Ranchero
@orti How is Carthage working for you? Is it "I'll never go back to cocoapods again" good?Alida
Carthage serves a good purpose, but right now (Nov 7, 2015) there's a lot of thrash in the development space around Xcode 7 and frameworks switching over from static libs to all dynamic. So half the time a dependency just doesn't work. Xcode 7 is establishing a new standard, and eventually we'll all adopt dynamic frameworks. Carthage's value is in pulling together dependencies quickly and keeping them all up to date. Cocoapods does a better overall job for OSS but worse for deploying code in a client project with private code dependencies.Ranchero
F
4

CouchbaseLite on iOS is a static framework, i.e. its binary is a static library not a dylib. This means it's linked into your app as though it were a source file. For this reason you don't use import in Swift to access it; the classes are already in the same namespace as your app's classes.

Fourlegged answered 24/9, 2015 at 17:40 Comment(0)
R
2

Unfortunately Cocoapods 0.39 suffers from "Transitive Vendor Dynamic Libraries Unsupported" You'll see this with the newest couchbase-lite-ios release including the binary CouchbaseLite.framework. This unfortunately issue bit me so hard I had to refactor everything to use Carthage, and manually manage my frameworks in my final projects.

Speaking of which the binary released CouchbaseLite.framework is simply missing a module map.

Add one to: CouchbaseLite.framework/Modules/module.modulemap

framework module CouchbaseLite {
  umbrella header "CouchbaseLite.h"

  export *
  module * { export * }
}

You will then be able to include this framework into a bridging header, and have your dynamic framework nest properly. But you might need to switch to building your CouchbaseKit.framework to using Carthage like I did.

Ranchero answered 19/10, 2015 at 6:58 Comment(3)
@Jens-Alfke I've noticed you mention it's available by default in swift global namespace in other comments, however I found it not appearing there, instead I had to add it to the bridging header and due to the missing modulemap you get a "No such module" error. This is in Xcode 7.1 beta 4, so maybe on prior Xcode releases you could be correct.Ranchero
@orti How is Carthage working for you? Is it "I'll never go back to cocoapods again" good?Alida
Carthage serves a good purpose, but right now (Nov 7, 2015) there's a lot of thrash in the development space around Xcode 7 and frameworks switching over from static libs to all dynamic. So half the time a dependency just doesn't work. Xcode 7 is establishing a new standard, and eventually we'll all adopt dynamic frameworks. Carthage's value is in pulling together dependencies quickly and keeping them all up to date. Cocoapods does a better overall job for OSS but worse for deploying code in a client project with private code dependencies.Ranchero
O
1

If you still want to use Cocoapods you can follow this

Steps:

  • Create a folder called the name of your Framework you want to use in that case CouchbaseLite and inside it create module map. The file name will be module.map and its content will be

module CouchbaseLite { header "../Pods/couchbase-lite-ios/CouchbaseLite.framework/Headers/CouchbaseLite.h" export * }

Important Note: Don't add that folder to the project, I don't know why not when done it will not work.

  • Import Paths under Swift Compiler – Search Paths in your project settings. Use ${SRCROOT} in the module path (e.g. ${SRCROOT}/CouchbaseLite) .

  • Then you can import it like any swift module.

Update: It will work nicely in Xcode, but when I have tried to validate the pod with the pod lint it still give error and I still don't know why.

Overleap answered 24/9, 2016 at 16:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.