Using Cocoapods to Extend an Application Using a Structure

I have an application (let it be called MyApp) written in Swift with the following goals:

  • MyApp : the main goal
  • MyAppKit : target framework for code that is used in conjunction with the application and its extension (s), mainly using the API and database processing
  • MyAppWidget : A Today View widget (or whatever it MyAppKit now) that uses the MyAppKit structure.

The MyAppKit structure MyAppKit tied to each goal that uses it, namely MyApp and MyAppWidget . Enter Cocoapods: I had the following Podfile structure:

 platform :ios, '8.0' use_frameworks! target 'MyApp' do # Mostly UI or convenience pods pod 'Eureka', '~> 2.0.0-beta' pod 'PKHUD', '~> 4.0' pod '1PasswordExtension', '~> 1.8' end target 'MyAppKit' do # Backend pods for networking, storage, etc. pod 'Alamofire', '~> 4.0' pod 'Fuzi', '~> 1.0' pod 'KeychainAccess', '~> 3.0' pod 'RealmSwift', '~> 2.0' pod 'Result', '~> 3.0' end target 'MyAppWidget' do # Added here event though the target only imports MyAppKit but it worked pod 'RealmSwift', '~> 2.0' end 

The goal here was to expose only the MyAppKit structure for other parts, and not for all its modules (for example, I do not want to be able to import Alamofire into the main application). However, starting with Cocoapods 1.2.0 RCs, pod install failed with the following error: [!] The 'Pods-MyApp' target has frameworks with conflicting names: realm and realmswift. It worked because containers were declared for expansion, but only embedded in the host application (see this issue for details). So I removed the containers from the widget's target, leaving me with only the empty target 'MyAppWidget' .

In this configuration, pod install runs fine, but compilation fails at the build stage for the purpose of MyAppWidget : ld: framework not found Realm for architecture x86_64 . This can be Realm.framework explicitly adding both Realm.framework and RealmSwift.framework to RealmSwift.framework "Link Binary With Libraries" and the following build parameter in the target Pods-MyAppWidget.[debug/release].xcconfig :

 FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Realm" "$PODS_CONFIGURATION_BUILD_DIR/RealmSwift"' 

However, whenever I run pod install , the build settings naturally return, and I need to add the build settings again.

I see the following solutions:

  • Add a post_install hook, adding these settings every time, but it seems to be “hacked” and after several erroneous attempts, I did not find an API link and I don’t know how to add these parameters to the MyAppWidget target through a script.
  • Change the subfile to the following structure (or even wrap it in an abstract target):

     [...] target 'MyAppKit' do # Backend pods for networking, storage, etc. pod 'Alamofire', '~> 4.0' pod 'Fuzi', '~> 1.0' pod 'KeychainAccess', '~> 3.0' pod 'RealmSwift', '~> 2.0' pod 'Result', '~> 3.0' target 'MyAppWidget' do inherit! :search_paths # Because else we get the "conflicting names" error end end 

    Which seems logical to me in the sense of “the widget needs to know where to look at the time of layout, but does not need containers as such,” but this does not add the above build settings (I'm probably wrong :search_paths inheritance) (edit: it works, but not with an abstract target). This idea came to me because in older versions of CocoaPods, the solution seemed to add link_with , which is now deprecated.

  • Expose Realm is also located in the target MyApp , however this contradicts my goal - not to have access to the "backend" code in the main code (can this be purely aesthetically pleasing?).

So here is my question: what is the best way to integrate containers into the infrastructure shared between the main application and the extension, while still being able to compile, without configuring or adding manually?

Greetings and thanks in advance!


EDIT

Following Prient’s remark, I explored the possibilities of abstraction and inheritance. The main problems that I have just uncovered are actually diverse:

  • He used to work in front of Cocoapods 1.2.0 because containers declared for the purpose of the widget were embedded in the host application, but were still associated with widgets. No, he simply refuses to have pods with the same name for different purposes in the ratio of “main versus expansion”
  • Using abstract targets is not enough, because goals cannot inherit only search paths ( inherit! :search_paths ) from the abstract target.
  • Search paths can be inherited from a real purpose, such as MyAppKit , but this provides all these MyApp code (which I want to avoid), and there is still a problem of linking the Realm structure (since the widget actually uses the smallest getter bit and therefore needs him).

Using this last option and manually binding Realm.framework works, but is suboptimal regarding my intentions and what was used to work. Some of these questions seem to be bug in line with various questions on GitHub Cocoapods. I have added my own problem and keep updating when I have news.

+13
ios swift cocoapods
source share
4 answers

So that gives:

  • My concern about “separating containers between targets” is absurd because you can still import them anywhere.
  • The "you must manually bind" problem is fixed by a simple import RealmSwift instructor.

Thus, the fixed and working subfile:

 platform :ios, '8.0' use_frameworks! target 'MyApp' do pod 'Eureka', '~> 2.0.0-beta' pod 'PKHUD', '~> 4.0' pod '1PasswordExtension', '~> 1.8' end target 'MyAppKit' do pod 'Fuzi', '~> 1.0' pod 'RealmSwift', '~> 2.0' pod 'Alamofire', '~> 4.0' pod 'KeychainAccess', '~> 3.0' pod 'Result', '~> 3.0' target 'MyAppWidget' do inherit! :search_paths end end 

What is it. I would say that the old behavior was more obvious and did not require reading "inheritance of the target podcast." However, I learned a lot. Hooray!

+9
source share

I do not know you. But for me it is completely legal and reasonable to have an extension, and the host application contains all the containers that the infrastructure defines. And here is what I mean:

 def shared_pods pod 'Alamofire' end target 'Framework' do shared_pods end target 'Host' do shared_pods // Some other pods end target 'Extension' do shared_pods end 

I know that you are worried, but if you think about it, you use all these third-party frameworks, they all have dependencies. You do not need to worry about them, because Cocoapods takes care of them for you. If you want to use this, then you will need to put a local block on the list.

 target 'Host' do pod Framework, :path => '../Framework' end 

But then you must support the podspec file.

+4
source share

This is an example of a SWIFT-3.0 project profile.

 platform :ios, '8.0' def import_public_pods pod 'SwiftyJSON' end target 'Demo' do use_frameworks! # Pods for Demo import_public_pods pod 'Fabric' pod 'Crashlytics' target 'DemoTests' do inherit! :search_paths # Pods for testing end target 'DemoUITests' do inherit! :search_paths # Pods for testing end end target 'DemoKit' do use_frameworks! # Pods for DemoKit import_public_pods pod 'RealmSwift' target 'DemoKitTests' do inherit! :search_paths # Pods for testing end end 
+1
source share

To disable the creation / launch of the created NSExtension, you need to:

  1. Click the project file in the project navigator.
  2. Click the containing target of the application (the one you want to run)
  3. Phase Assembly Tab
  4. Open Target Dependencies
  5. Remove the extension (the one you DO NOT want to run)
  6. To return it, simply click the + sign in the same place and add it again.

In my case, working successfully

0
source share

All Articles