I am trying to create a Dynamic Framework to share the code among various extensions of my app.
Problem :
Here is my project structure.
MyFrameworks is a network layer of my app which inherently uses Alamofire. So structured my pod file as follow.
platform :ios, '9.0'
use_frameworks!
workspace 'CocoaPodsProjectworkspace'
def shared_pods
pod 'Alamofire'
pod 'SwiftyJSON'
end
target 'CocoaPodsProject' do
project 'CocoaPodsProject.xcodeproj'
# Pods for CocoaPodsProject
end
target 'MyFramework' do
project 'MyFramework/MyFramework.xcodeproj'
shared_pods
end
target 'CocoaPodsProjectTests' do
end
target 'CocoaPodsProjectUITests' do
end
On building the framework when I drag it as embedded binary to my Main project I get the error.
dyld: Library not loaded: .framework/Alamofire Referenced from: /Users/sandeep/Library/Developer/Xcode/DerivedData/CocoaPodsProjectworkspace-enpobdyluhbxdwazuvbfogcspfof/Build/Products/Debug-iphonesimulator/MyFramework.framework/MyFramework Reason: image not found
Solutions I tried :
- Declaring the pods_frameworks.framework as optional in linked binaries.
- Tried changing RunPath Search path of framework Dynamic Library
- Install name Running pod deintegrate and running pod install again.
- Deleting derived data and relinking framework all lead to same problem.
Solution that worked :
I realized that MyFramework.framework was trying to find the Alamofire.framework in a wrong directory and it was alway trying to search relative to project/target using the framework . So the simplest solution that I could find was to modify pod file as follow.
platform :ios, '9.0'
use_frameworks!
workspace 'CocoaPodsProjectworkspace'
def shared_pods
pod 'Alamofire'
pod 'SwiftyJSON'
end
target 'CocoaPodsProject' do
project 'CocoaPodsProject.xcodeproj'
shared_pods
# Pods for CocoaPodsProject
end
target 'MyFramework' do
project 'MyFramework/MyFramework.xcodeproj'
shared_pods
end
target 'CocoaPodsProjectTests' do
end
target 'CocoaPodsProjectUITests' do
end
As you can see I added the shared_pods to both main app and my framework project and their respective targets. Now everything works smooth. I neither had to make pods_framework optional nor had to modify the build settings of MyFramework.
Question:
Adding the shared repos to all the projects and their targets which wants to use my framework looks little redundant. Is there a better way I can specify Myframework.framework to read all its dependencies rather than reading from project using it?
I have raised a issue for the same on CocoaPods Git repo. But because it isn't inherently a issue they might not revert back. Hence posting it as a question here.Link to issue : https://github.com/CocoaPods/CocoaPods/issues/6901 if it helps.
Solved it by creating a cocoa pod for my custom Framework and using cocoa pods dependency .
Step 1 : Clean the Main/Parent project
pod deintegrate
(to de-integrate the pod already added toproject)
pod init
Step 2: Create a Pod for my Framework
pod spec create MyFramework
This will create a file named MyFramework.podspec in the MyFramework's root folder. Open MyFramework.podspec using any of the editor tool and update it as shown in tutorial https://www.raywenderlich.com/126365/ios-frameworks-tutorial
Most important step which is not there in this tutorial is how to add cocoa pods dependency that our framework needs to build. Turns out thats the most easiest part. In my case I needed
SwiftyJSON
andAlamofire
so in .podspec file I added,Step 3:
Podfile
and update it as shown below.What it did is, it tells main project to add TestFramework as dependency and installs TestFramework in Framework folder of main project. Because TestFramework in itself has dependency to
Alamofire
&SwiftyJSON
when you runpod install
it will not only installAlamofire
but also installsSwiftyJSON
and adds it toTestFramework's
Framework folder.Thats all. Now your TestFramework can access
Alamofire
andSwiftyJSON
and Main/Patent project can accessTestFramework
If you want to now update TestFramework code, till u finish develop add it as subproject to Main project (This is necessary because if you open TestFramework.xcproj u won't see Alamofire/Swifty JSON. You have to open the Parent project's workspace itself hence this solution). Once u are done with development if u decide to remove the TestFramework as subproject u can do that :)
Finally If you decide to add additional extensions to app, Lets say u add Today extension all u have to do is to modify ur Podfile as follow.
Woo hooo :) Now add your frameworks to as many extensions you want :) Hope it helps.