J'ai une application (appelons-la MyApp) écrite en Swift avec les cibles suivantes:
MyApp
: la cible principaleMyAppKit
: une cible construisant un framework pour le code qui est partagé entre l'application et ses extensions, principalement le backend API et la gestion de la base de donnéesMyAppWidget
: un Widget de Vue Aujourd'hui (ou son nom actuel) qui utilise le framework MyAppKit
.Le framework MyAppKit
est lié à chaque cible qui l'utilise, à savoir MyApp
et MyAppWidget
. Entrez Cocoapods: J'avais auparavant la structure 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 pods (par exemple, je ne veux pas pouvoir import Alamofire
dans l'application principale). Cependant, en commençant par les Cocoapods 1.2.0 RC, pod install
a échoué avec l'erreur suivante: [!] The 'Pods-MyApp' target has frameworks with conflicting names: realm and realmswift.
. Cela fonctionnait parce que les pods ont été déclarés pour l'extension mais uniquement intégrés dans l'application hôte (voir ce problème pour plus d'informations). J'ai donc supprimé les pods de la cible du widget, me laissant juste un _ target 'MyAppWidget'
ligne.
Avec cette configuration, pod install
s'exécute correctement mais la compilation échoue au stade de la liaison pour la cible MyAppWidget
: ld: framework not found Realm for architecture x86_64
. Cela peut être résolu en ajoutant explicitement les deux Realm.framework
et RealmSwift.framework
à la section "Link Binary With Libraries" et au paramètre de génération suivant dans le Pods-MyAppWidget.[debug/release].xcconfig
:
FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Realm" "$PODS_CONFIGURATION_BUILD_DIR/RealmSwift"`
Cependant, chaque fois que je lance pod install
, les paramètres de build sont naturellement rétablis et je dois à nouveau ajouter les paramètres de build.
Je vois les solutions suivantes:
post_install
hook ajoutant ces paramètres à chaque fois mais cela semble "hacky" et après quelques tentatives malencontreuses, je n'ai trouvé aucune référence API et je ne sais pas comment ajouter ces paramètres à la cible MyAppWidget
via le script.Changez le Podfile en 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ù chercher lors de la liaison mais n'a pas besoin des pods en soi" mais cela n'ajoute pas les paramètres de construction susmentionnés (je comprends probablement mal le (modifier: 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 devait apparemment ajouter :search_paths
héritage)link_with
, désormais obsolète.
MyApp
, mais cela entre en conflit avec mon objectif de ne pas avoir accès au code "backend" dans le code principal (cela pourrait être purement esthétique?).Alors, voici ma question: quelle est la meilleure façon d'intégrer des pods dans un cadre partagé entre l'application principale et l'extension tout en étant en mesure de compiler, sans peaufiner et ajouter manuellement des choses?
Santé et merci d'avance!
Après Commentaire de Prientus J'ai exploré les possibilités d'abstraction et d'héritage. Les problèmes sous-jacents que j'ai maintenant découverts sont en fait multiples:
inherit! :search_paths
) à partir d'une cible abstraite.MyAppKit
, mais cela expose tous ces pods au code de MyApp
(que je veux éviter), et il y a toujours le problème de la liaison du framework Realm (car en fait, le widget utilise le plus petit bit d'un getter et en a donc besoin).Utiliser cette dernière option et lier manuellement Realm.framework fonctionne mais n'est pas optimal en ce qui concerne mes intentions et ce qui fonctionnait auparavant. Certains de ces problèmes semblent être un bogue selon diversproblèmeson GitHub de Cocoapods. J'ai ajouté mon propre problème et je mettrai à jour quand j'aurai des nouvelles.
Alors, qu'est-ce qui donne:
import RealmSwift
déclaration.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 lecture sur "l'héritage de la cible du podfile". J'ai cependant beaucoup appris. À votre santé!
Je ne te connais pas. Mais pour moi, c'est totalement légitime et raisonnable d'avoir l'extension et l'application Host contient tous les pods qu'un framework définit. Et c'est 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 êtes inquiet, mais si vous y réfléchissez, tous ces cadres tiers que vous utilisez, ils ont tous des dépendances. Vous n'avez pas à vous en préoccuper car Cocoapods s'en occupe pour vous. Si vous souhaitez utiliser cela, vous devrez mettre une entrée de pod local dans la liste.
target 'Host' do
pod Framework, :path => '../Framework'
end
Mais alors vous devez maintenir le fichier podspec
.
Il s'agit d'un 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