J'ai une application (appelons-la MyApp) écrite dans Swift avec les cibles suivantes:
MyApp
: la cible principale MyAppKit
: une cible établissant un cadre pour le code partagé entre l'application et ses extensions, principalement le backend de l'API et la gestion de la database MyAppWidget
: un widget "Vue d'aujourd'hui" (ou quel que soit son nom actuel) qui utilise le framework MyAppKit
. Le framework MyAppKit
est lié à chaque cible qui l'utilise, à savoir MyApp
et MyAppWidget
. Entrer Cocoapods: J'avais l'habitude d'avoir la structure de Podfile suivante:
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
Le but ici était d'exposer uniquement le framework MyAppKit
aux autres parties et pas à tous ses modules (par exemple, je ne veux pas pouvoir import Alamofire
dans l'application principale). Cependant, en commençant par les RC Cocoapods 1.2.0, l' pod install
échoué avec l'erreur suivante: [!] The 'Pods-MyApp' target has frameworks with conflicting names: realm and realmswift.
. Cela fonctionnait parce que les pods étaient déclarés pour l'extension mais seulement embeddeds dans l'application hôte (voir ce numéro pour plus d'informations). J'ai donc retiré les pods de la cible du widget, me laissant avec juste une ligne target 'MyAppWidget'
.
Avec cette configuration, l' pod install
s'exécute MyAppWidget
mais la compilation échoue à l'étape de binding pour la cible MyAppWidget
: ld: framework not found Realm for architecture x86_64
. Cela peut être corrigé en ajoutant explicitement à la fois le Realm.framework
et le RealmSwift.framework
à la section "Link Binary With Libraries" et le paramètre de construction suivant dans les Pods-MyAppWidget.[debug/release].xcconfig
la cible Pods-MyAppWidget.[debug/release].xcconfig
:
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Realm" "$PODS_CONFIGURATION_BUILD_DIR/RealmSwift"`
Cependant, chaque fois que pod install
, les parameters de construction sont naturellement inversés et je dois à nouveau append les parameters de construction.
Je vois les solutions suivantes:
post_install
ajoutant ces parameters à chaque fois, mais cela semble "hacky" et après quelques tentatives mal orientées, je n'ai trouvé aucune reference d'API et je ne sais pas comment append ces parameters à la cible MyAppWidget
par le biais du script. Remplacez le file Podfile par la structure suivante (ou même en l'enveloppant dans une cible abstraite):
[...] 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
Ce qui me semble logique dans le sens de "le widget devrait savoir où regarder pendant la binding mais n'a pas besoin des pods en soi" mais cela n'ajoute pas les parameters de construction mentionnés précédemment (je me : cela fonctionne réellement, mais pas avec une cible abstraite). Cette idée m'est venue parce que dans les anciennes versions de CocoaPods, la solution était apparemment d'append :search_paths
probablement l'inheritance :search_paths
)link_with
, qui est maintenant obsolète.
MyApp
, mais cela est en conflit avec mon objective de ne pas avoir access au code "backend" dans le code principal (il pourrait être purement esthétique?). Alors, voici ma question: quel est le meilleur moyen d'intégrer des pods dans un cadre partagé entre l'application principale et l'extension tout en étant capable de comstackr, sans avoir à modifier et append manuellement des choses?
Santé et merci d'avance!
Après le commentaire de Prientus, j'ai exploré les possibilités de l'abstraction et de l'inheritance. Les problèmes sous-jacents que j'ai maintenant découverts sont en fait multiples:
inherit! :search_paths
) d'une cible abstraite. MyAppKit
, mais cela expose tous ces pods au MyApp
de MyApp
(que je veux éviter), et il y a toujours le problème de lier le framework Realm (parce que le widget utilise le plus petit peu de getter et en a donc besoin). Utiliser cette dernière option et relier manuellement Realm.framework fonctionne mais est sous-optimal quant à mes intentions et ce qui fonctionnait. Certains de ces problèmes semblent être un bug selon divers problèmes sur GitHub de Cocoapods. J'ai ajouté mon propre numéro et je vais le mettre à jour quand j'ai des nouvelles.
Alors, qu'est-ce qui donne:
import RealmSwift
facile à import RealmSwift
. Le Podfile fixe et fonctionnel est donc:
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
Et c'est tout. Je dirais que l'ancien comportement était plus évident et ne nécessitait pas de lire sur "l'inheritance de la cible podfile". J'ai beaucoup appris cependant. À votre santé!
Je ne te connais pas. Mais pour moi, il est totalement légitime et légitime que l'extension et l'application hôte contiennent tous les modules définis par un framework. Et voici ce que je veux dire:
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
Je sais que vous vous inquiétez, mais si vous y réfléchissez, tous les frameworks tiers que vous utilisez, ils ont tous des dependencies. Vous n'avez pas à vous soucier d'eux parce que Cocoapods prend soin d'eux pour vous. Si vous voulez utiliser cela, vous devez mettre une input de pod local dans la list.
target 'Host' do pod Framework, :path => '../Framework' end
Mais alors vous devez maintenir le file podspec
.
C'est l'exemple de profil d'un projet swift-3.0.
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