简体   繁体   中英

Is this the correct way to create dynamic/embedded framework with embedded cocoa pods?

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

  • Removed MyFramework from the project (which was added as sub project) and remove MyFramework.framework added in embedded library of projects General settings.
  • Run pod deintegrate (to de-integrate the pod already added to
    project)
  • Now that the project is clean and does not have any pod added initialized the pod by running pod init

Step 2: Create a Pod for my Framework

  • Using cd command navigate to MyFramework project and once you are in MyFramework's root folder run 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 and Alamofire so in .podspec file I added,

s.dependency 'Alamofire'

s.dependency 'SwiftyJSON'

Step 3:

  • Now open the Main/Parent projects Podfile and update it as shown below.
 target 'CocoaPodsProject' do use_frameworks! pod 'TestFramework', :path => 'TestFramework/' end 

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 run pod install it will not only install Alamofire but also installs SwiftyJSON and adds it to TestFramework's Framework folder.

Thats all. Now your TestFramework can access Alamofire and SwiftyJSON and Main/Patent project can access TestFramework

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.

target 'CocoaPodsProject' do
  use_frameworks!
  pod 'TestFramework', :path => 'TestFramework/'
end

target 'CocoapodsToday' do
  use_frameworks!
  pod 'TestFramework', :path => 'TestFramework/'
end

Woo hooo :) Now add your frameworks to as many extensions you want :) Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM