iOS: Migrating Cocoapods from Dynamic Libraries to Static Libraries - ios

I am trying to transition from dynamic libraries (via use_frameworks!) to static libraries in a project that the uses cocoapods to handle external dependencies. The project is a combo of swift & objc.
One of these dependencies is an internal swift cocoapod. However, when I try to build, I get the following message:
Cannot load underlying module <our_internal_cocoapod>
Additionally, the ProjectName-swift.h is not found, I am assuming it is not being generated.
Things I've tried:
1. cleaning & building
2. deleting derived data
3. reinstalling cocoa pods
All to no avail. How can I resolve this? Help greatly appreciated!

Static libraries don't provide module access by default.
CocoaPods 1.5.0 introduced use_modular_headers! to still provide module support with static libraries. Details in the release notes.
If you run into issues with that, you may want to try the 1.6.0 beta which has some bug fixes in this area.

Related

How can I use ` use_frameworks!` to a specific cocoapods pod?

I know if you are using Cocoapods, you should use all pods as framework or static libraries. It's not possible specify some pods using framework and the others using static library. But I just want to have a try to ask or discussion about this problem. Maybe there will be some tricky solutions. ^_^
I am working on a iOS project, Objective-C as the main development language. Now I want to import a swift framework using Cocoapods, I didn't use use_frameworks!, some problems occurs as expected. The Cocoapods version is 1.5.3, Swift 5.0, is there a way or a new version to solve this problem? How about Carthage?
Any discussion is appreciate!
CocoaPods 1.9.0 is adding support for specifying linkage on individual pods. Until then, the only option is Podfile hacks like this one.

How to use cocoapods in xamarin.ios

I would like to make use of couple of cocoapods in my xamarin.ios project.
But I couldn't find those cocoapods in Nuget which is package manager for Xamarin.
I heard we can compile a xcode project into a static library ... that is .a file and use it in xamarin.
But I am getting confused on how to convert the pods into a static library or something so that I can use those pods in my xamarin.
You cannot take the Pod directly and create a static library but you can although create a static library from the Pod project which already contains your pod. But to be honest the best solution will be getting the source code of the project and create the static library from there. Most of the Pods out there are open source so grabbing the source code from github should not be a problem.
Once you have the source code follow this example to show you how to create static libraries from there.
Once you have created the static library you just need to follow this tutorial to create a Binding library that can be used in Xamarin.
Unfortunately AFAK there's not support yet for Swift libraries to create binding libraries so this will only work with objective-c code.

Embedding frameworks inside closed-source Swift framework

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?
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:
In project target, make sure to add Pods.framework to Linked Frameworks and Libraries (make sure this is a pre-compiled RED version of Pods.framework, I had a black compiled Pods.framework in the same directory which built fine but then resulted in a framework that would cause the project to complain about missing armv7 architecture during linker phase in later project)
In Build Settings, under User-Defined section, add a field called BITCODE_GENERATION_MODE and set it to bitcode
DO NOT #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)
Change build target to Generic iOS Device, Archive and Export the framework
When building the project using the framework:
Drag and drop the framework into the project, in General tab add it to Embedded Binaries and Linked Frameworks and Libraries (you only need to add the framework itself, not the sub-frameworks or the pods file)
In Build Settings tab, add a new path to Framework Search Paths: $(PROJECT_DIR)/MyFramework.framework/Frameworks
Build the project

Cocoa Touch Framework Dependencies

I'm trying to create a Cocoa Touch Framework. To create a framework is not a problem, I used this tutorial and it is good.
I need to use third party libraries inside: like openssl, XLForm, AFNetworking. I know that it is not correct to include them in my framework, I need to create a dependencies, but I can't find how to do this.
Moreover is it possible to use pods in my framework and just make dependencies to these libs. So user which will include my framework to his project will need just install these pods.
It seems that I found solution.
Thanks to #Droppy and thanks to this question.
What I did: I just installed pods to my Framework project but used this use_frameworks! key.
Then I dragged my Framework to my Project and installed pods there, also with same key, otherwise (when pod wasn't installed in my Project) I was getting error like:
dyld: Library not loaded: #rpath/XLForm.framework/XLForm...
I used XLForm inside my Framework.

Creating static library which depends on other static library (RestKit)

I followed the following tutorial to create a static library:
https://github.com/jverkoey/iOS-Framework/#developing-the-framework-as-a-dependent-project
It all works until I try to incorporate the RestKit into my static library. There I am completely lost. Am I supposed to include the RestKit library into my static library or only in the App which will use my library?
If I don't include RestKit in my library, I can't compile it as it depends on another library (RestKit) so what would be workaround for this?
I tried to look everywhere but haven't found a good step by step tutorial to create a static library which itself depends on other static libraries.
What I did to get this working was to add RestKit to my static library using their git-submodule instructions here. Then I performed the exact same steps on the projects that were going to use my static library EXCEPT:
I did not add RestKit to the "Target Dependency" section of the Build Phases
I did not add the libRestKit.a to the "Link Binary With Libraries" section. All other references still needed to be added.
I was then able to reference RestKit in both my static library and my iOS project.
COCOAPODS MEGA HACK
I was able to get this working with cocoa pods, but it will only work if this is your only cocoapods project. I started with all of my projects in a single workspace. Then I had my single podfile install RestKit to my static library and all projects that were going to reference my static library. Then for each project that I wanted to reference my static library I removed the pod reference under "Linked Frameworks and Libraries". Everything was then working as expected.
As you can expect, this would probably break all other pod references (unless you managed them all through that one static library), but it does seem to work.
Shorty after asking the question I finally managed to get it working here the steps if someone has a similar problem:
Create an actual app as explained int this section. After adding your library add all the other libraries you use to the application. (In my case it was the RestKit framework, add it as a submodule and not with cocoapods as with cocoa pods it didn't manage to get it to work properly).
After adding all your libraries, follow the third party libraries instruction for modification for the application and make the same modification for your static library.
e.g. for Restkit I had to add
-ObjC -all_load
to the Other Linker Flags and add
"$(BUILT_PRODUCTS_DIR)/../../Headers"
to the Header Search Path inside my static library.
I still couldn't build as the <RestKit/Restkit.h> wasn't found, so I needed to change the build order of the frameworks to assure that Restkit was built before my library.
This is done inside the edit Scheme of the build menu. Make sure that all the dependent libraries are on top of your library (if your static library or the dependent libraries aren't already in there add them with the '+')
Afterward everything worked for me. I am not sure if this is the best method to do it or if it would be better to include the third party library inside your statistic library.
Update I still run into problems when trying to build my library, if someone has a better solution or can shed some light on how to create a static framework which depends on other frameworks I would appreciate it.

Resources