Our company wants to distribute a closed-source SDK for iOS to our clients. I've been using Cocoapods to build the framework and built an example app making use of it. Previously the app worked fine on the simulator as well as when deployed on the device. However, I was also embedding the Pods.framework file in the app itself. One other piece of information that may be of interest is that the framework is written in Swift, the included cocoapods dependencies are both Swift and Objective-C.
I wanted to make the pods requirements easier to manage so the user doesn't need to be concerned with them and tried to embed the Pods.framework file inside of the SDK we're building - so I removed the steps to Embed Pods Frameworks and Copy Pods Resources from the example app, leaving them only in the framework, I also removed Pods.framework as a dependency of the example app, leaving it only in the SDK. This seemed to work in the simulator, but the app now crashes on mobile device with dyld: Library not loaded error.
Upon researching it, I stumbled into a few related discussions: https://github.com/CocoaPods/CocoaPods/issues/344 https://objectpartners.com/2014/06/25/developing-private-in-house-libraries-with-cocoapods/
However, the suggested solution of using private pods does not look like it would work for us, it's my understanding that the source code in the private pod would still be open, and we can't share it with our clients.
Could someone advise on a solution that would work in this case?
To distribute code in binary form as a Swift package, create an XCFramework bundle, or artifact, that contains the binaries. Then, make the bundle available locally or on a server: When you host the binaries on a server, create a ZIP archive with the XCFramework in its root directory and make it available publicly.
Embedding a Framework in iOS, macOS, watchOS, and tvOS AppsOpen the app's Xcode project or workspace. Go to the app target's General configuration page. Add the framework target to the Embedded Binaries section by clicking the Add icon, highlighted in Figure 5. Do not drag in the framework from Finder.
Distributing compiled framework through CocoapodsCreate a git repository to hold Cocoapods specifications files in our home directory. Create a git repository in our home directory to hold the compiled MyFramework. Create and push MyFramework specification to our Cocoapods specification repository created in step 1.
OK, I finally have a more durable solution. It's a modified, cleaner version of my old one now that I understand how Xcode links in my Swift sub-frameworks better
Problem that makes distribution/compilation a bit ugly:
Since Swift standard libraries aren't bundled on the device like Obj-C, nor are they guaranteed to be stable between versions yet (stable binary interface promised in Swift 3: https://github.com/apple/swift-evolution#development-major-version--swift-30) we have to make sure the entire project is compiled against the same version of Swift. That means the guy using your closed-source framework has to be using the same version of Swift in their Xcode for their project as you did for compiling the library, even if he's not using Swift in his code because ultimately it's his version of Swift that gets bundled into the app and your SDK runs against. This is only an issue for closed-source frameworks because open-source ones will always be compiled against the same version as final project. Possible workaround is to restrict clients to same version you use or distribute multiple compilations (i.e. Swift 2.1 and Swift 2.0). To remedy this, you could provide users with copies of binaries compiled against multiple versions of Swift.
Aside from that, here is what I had to do during compilation/distribution to make a binary framework that works in Swift:
When building the framework:
#import
any frameworks in your bridging header, all instructions telling you to do that are leftover from Swift 1.0-1.2 days, you don't need it anymore and it does more harm than good (the later project will complain that it can't find these headers that aren't even exposed to it)When building the project using the framework:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With