Avec Xcode 6 nous obtenons la possibilité de créer notre propre dynamique Cocoa Frameworks
.
En raison de:
Le simulateur utilise toujours la bibliothèque 32-bit
à compter du 1er juin 2015, les mises à jour d'applications soumises sur l'App Store doivent inclure une prise en charge 64 bits et être générées avec le SDK iOS 8 ( developer.Apple.com )
Nous devons créer une grosse bibliothèque pour exécuter des projets sur des appareils et des simulateurs. c'est-à-dire prendre en charge les formats 32 et 64 bits dans les cadres.
Mais je n'ai trouvé aucun manuel, comment exporter le cadre universel pour une intégration future avec d'autres projets (et partager cette bibliothèque avec quelqu'un).
Définissez ONLY_ACTIVE_Arch=NO
Dans le Build Settings
Ajouter le support armv7 armv7s arm64 i386 x86_64
À Architectures
(bien sûr)
Mais au final, je rencontre toujours un problème pour exécuter un projet avec ce framework sur les appareils et le simulateur à la fois.
si je prends le cadre du dossier Debug-iphoneos
- il fonctionne sur les appareils et génère une erreur sur les simulateurs: ld: symbol(s) not found for architecture i386
xcrun lipo -info CoreActionSheetPicker
Les architectures dans le fichier fat: CoreActionSheetPicker sont: armv7 armv7s arm64
si je prends le cadre du dossier Debug-iphonesimulator
- cela fonctionne sur les simulateurs. et j'ai une erreur sur le périphérique: ld: symbol(s) not found for architecture arm64
xcrun lipo -info CoreActionSheetPicker
Les architectures dans le fichier fat: CoreActionSheetPicker sont: i386 x86_64
Cette réponse concernait Xcode 6 iOS Création d'un framework Cocoa Touch Framework - Problèmes d'architecture mais ce n'est pas un doublon.
J'ai trouvé un "hack sale" pour cette affaire. Voir mon réponse ci-dessous . Si quelqu'un sait plus pratique - s'il vous plaît, faites le moi savoir!
L’actualité de cette réponse est: juillet 2015. Il est fort probable que les choses vont changer.
TLDR;
Actuellement, Xcode ne dispose pas d'outils pour l'exportation automatique du framework fat universel. Le développeur doit donc recourir à l'utilisation manuelle de l'outil lipo
. Toujours selon ce radar avant d'être soumis au développeur de l'AppStore qui est le consommateur du framework, il doit également utiliser lipo
pour supprimer les tranches du simulateur d'un framework.
Réponse plus longue suit
J'ai fait des recherches similaires sur le sujet (le lien au bas de la réponse).
Je n'avais trouvé aucune documentation officielle sur la distribution de mes produits, mes recherches étaient donc basées sur l'exploration de Apple Forums de développeurs, projets Carthage et Realm et mes propres expériences avec xcodebuild
, lipo
, codesign
outils.
Voici une longue citation (avec un peu de balisage de ma part) de Apple Exportation de l'application avec un cadre intégré :
Quelle est la bonne manière d'exporter un framework depuis un projet framework?
Actuellement, le seul moyen est exactement ce que vous avez fait:
- Construisez la cible pour le simulateur et le périphérique iOS.
Naviguez jusqu'au dossier DerivedData de Xcode pour ce projet et lissez les deux fichiers binaires dans un seul et même framework. Toutefois, lorsque vous créez la cible de structure dans Xcode, veillez à ajuster le paramètre de cible "Construire une architecture active uniquement" sur "NON". Cela permettra à Xcode de construire la cible pour plusieurs types de binarty (arm64, armv7, etc.). Ce serait pourquoi cela fonctionne à partir de Xcode mais pas comme un binaire autonome.
Vous devrez également vous assurer que le schéma est défini sur une version Release et construire la cible de l'infrastructure par rapport à Release. Si vous obtenez toujours une erreur de bibliothèque non chargée, vérifiez les tranches de code dans la structure.
- Utilisez
lipo -info MyFramworkBinary
Et examinez le résultat.
lipo -info MyFrameworkBinary
Le résultat est
i386 x86_64 armv7 arm64
- Les frameworks universels modernes comprendront 4 tranches, mais pourraient en inclure davantage:
i386 x86_64 armv7 arm64
Si vous ne voyez pas au moins ce 4, cela pourrait être dû au paramètre Build Active Architecture.
Ceci décrit un processus similaire à celui que @skywinder a fait dans sa réponse.
C’est ainsi que Carthage utilise lipo et Le royaume utilise lipo .
DÉTAIL IMPORTANT
Il y a un radar: Xcode 6.1.1 et 6.2: les frameworks iOS contenant des tranches de simulateur ne peuvent pas être soumis à l'App Store et une longue discussion à ce sujet sur Domaine # 116 et Carthage # 188 qui s'est terminé par une solution spéciale:
avant la soumission à l'AppStore iOS, les fichiers binaires du framework doivent être supprimés des tranches du simulateur
Carthage a un code spécial: CopyFrameworks et la documentation correspondante:
Ce script fonctionne autour d'un bug de soumission dans l'App Store déclenché par des fichiers binaires universels.
Le domaine a un script spécial: strip-frameworks.sh et la documentation correspondante:
Cette étape est nécessaire pour contourner un bogue de soumission d'App Store lors de l'archivage de fichiers binaires universels.
Il existe également un bon article: Suppression des architectures indésirables des bibliothèques dynamiques dans Xcode .
J'ai moi-même utilisé le logiciel strip-frameworks.sh
De Realm, qui a parfaitement fonctionné sans aucune modification, même si, bien entendu, tout le monde est libre d'en écrire un de toutes pièces.
Le lien vers mon sujet que je recommande de lire car il contient un autre aspect de cette question: signature de code - Création de cadres iOS/OSX: est-il nécessaire de les coder avant de les distribuer à d'autres développeurs?
Ce n'est pas une solution si claire, mais il y a un moyen, que je trouve:
Ensemble ONLY_ACTIVE_Arch=NO
dans le Build Settings
Ouvrir le dossier console Products
de votre framework (vous pouvez l’ouvrir en ouvrant le dossier framework et cd ..
à partir de là)
Products
. Cela crée un gros framework dans ce dossier. (ou faites-le manuellement comme expliqué ci-dessous dans 3. 4. )Ou:
Combinez ces 2 cadres en utilisant lipo par ce script (remplacez YourFrameworkName
par le nom de votre cadre)
lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"
Remplacez par un nouveau binaire parmi les cadres existants:
cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework
mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName
./YourFrameworkName.framework
- est un gros binaire prêt à l'emploi! Vous pouvez l'importer dans votre projet!Pour les projets, cela ne se fait pas dans les espaces de travail:
Vous pouvez également essayer d'utiliser ce Gist comme décrit ici . Mais il semble que cela ne fonctionne pas pour les projets dans les espaces de travail.
La réponse de @Stainlav a été très utile, mais j’ai plutôt choisi de compiler deux versions du cadre (une pour l’appareil et une pour le simulateur), puis d’ajouter le Run Script Phase
pour copier automatiquement le framework précompilé requis par l’architecture en cours
echo "Copying frameworks for architecture: $CURRENT_Arch"
if [ "${CURRENT_Arch}" = "x86_64" ] || [ "${CURRENT_Arch}" = "i386" ]; then
cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active"
else
cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active"
fi
De cette façon, je n'ai pas utilisé lipo
pour créer un framework fat ni le domaine du royaume strip-frameworks.sh
pour supprimer les tranches inutiles lors de la soumission à l'App Store.
fondamentalement, j'ai trouvé une très bonne solution. il vous suffit de suivre ces étapes simples.
lipo-create 'device/MonFramework.framework/MonFramework' 'simulateur/MyFramework.framework/MyFramework' -output 'MyFramework.framework/MyFramework'
et c'est tout. Ici, nous fusionnons le simulateur et la version de périphérique du fichier binaire MyFramework dans MyFramework.framework. Nous obtenons un cadre universel qui construit pour toutes les architectures, y compris les simulateurs et les appareils.
Je veux juste mettre à jour cette excellente réponse par @odm. Depuis Xcode 10, la variable CURRENT_Arch
Ne reflète plus l'architecture de construction. J'ai donc changé le script pour vérifier la plateforme à la place:
echo "Copying frameworks for platform: $PLATFORM_NAME"
rm -R "${SRCROOT}/Frameworks/Active"
if [ "${PLATFORM_NAME}" = "iphonesimulator" ]; then
cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active"
else
cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active"
fi
J'ai également ajouté une ligne pour effacer le répertoire cible avant la copie, car j'avais remarqué que les fichiers supplémentaires des sous-répertoires ne seraient pas écrasés autrement.
Ma réponse couvre les points ci-dessous:
Créer un framework qui fonctionne à la fois pour le simulateur et pour le périphérique
Comment exporter "gras" Cocoa Touch Framework (à la fois pour Simulator et Device)?
Symboles non définis pour l'architecture x86_64
ld: symbole (s) non trouvé (s) pour l'architecture x86_64
Etapes 1: commencez par construire vos frameworks avec la cible Simulator
Etape 2: Une fois le processus de construction du simulateur réussi, créez maintenant votre infrastructure avec la sélection de cible de périphérique ou la sélection de périphérique iOS générique.
Étape 3: Maintenant, sélectionnez votre cible de structure et pour cela Sous "phases de construction", sélectionnez "Ajouter un script d'exécution" et copiez le code de script ci-dessous)
Étape 4: Enfin, construisez à nouveau et votre infrastructure est prête pour la compatibilité du simulateur et du périphérique. Hourra!!!!
[Remarque: nous devons avoir les deux cadres compatibles prêts avant l'étape finale 4 (simulateur et architecture de périphérique compatibles, sinon, veuillez suivre les étapes 1 et 2 ci-dessus correctement)
Voir l'image de référence:
Mettez le code ci-dessous dans la zone de shell:
#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_Arch=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_Arch=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# Step 2. Copy the framework structure (from iphoneos build) to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory
SIMULATOR_Swift_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/."
if [ -d "${SIMULATOR_Swift_MODULES_DIR}" ]; then
cp -R "${SIMULATOR_Swift_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
fi
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# Step 5. Convenience step to copy the framework to the project's directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
# Step 6. Convenience step to open the project's directory in Finder
open "${BUILD_DIR}/${CONFIGURATION}-universal"