web-dev-qa-db-fra.com

Xcode 6 et les cadres intégrés pris en charge uniquement par iOS8

Lors de l'utilisation d'une infrastructure intégrée (dyld) dans Xcode 6.0.1 avec une cible de déploiement inférieure à iOS 8, je reçois:

  • La construction est réussie
  • Erreur de chargement de la bibliothèque d'exécution

Erreur:

dyld: Library not loaded: @rpath/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2        
Referenced from: /private/var/mobile/Containers/Bundle/Application/DC65ACA9-98E5-46CD-95F8-829D3416F6C0/musiXmatch.app/musiXmatch
Reason: image not found
(lldb) 
68
loretoparisi

Pendant un certain temps, je pensais que c’était aussi mon problème, mais pour les applications normales (extension non-iOS-8), il vous suffit de modifier un paramètre de construction dans votre environnement universel Xcode 6 iOS Universal Framework occasionnel. target (définit le type Mach-O sur Static Library):

Set it to Static Library

Il ne devrait y avoir aucun problème avec iTunes Connect et iOS 7 après cela :)

39
Maciek Czarnik

À l'heure actuelle, il n'existe aucun moyen d'utiliser un framework intégré pour partager du code entre une application et un widget et le faire fonctionner sur iOS 8 ainsi que sur iOS 7 et versions antérieures.

Voici quelques lectures supplémentaires à ce sujet http://atomicbird.com/blog/ios-app-extension-tips

Frameworks vs iOS 7

Si vous partagez du code entre une application et une extension, vous pouvez créer votre propre framework intégré pour contenir le code. Sur iOS 8, il se charge dynamiquement dans les deux cas, vous êtes donc prêt.

Si vous supportez toujours iOS 7 (ou une version antérieure), ce n'est pas si clair. Les frameworks embarqués ne fonctionnent pas là. Le Guide de programmation des extensions d'application indique clairement que vous pouvez utiliser dlopen pour résoudre ce problème. Avec cette approche, vous écrivez du code pour charger dynamiquement la structure au moment de l'exécution plutôt que de vous fier à iOS pour le charger pour vous, si vous avez vérifié que le code s'exécute sur une version d'iOS qui le permet.

Mais comment utilisez-vous ce code sur iOS 7? Vous pas. Si votre code partagé se trouve dans une infrastructure intégrée, vous ne pouvez pas l'exécuter sur iOS 7. Il est tout simplement indisponible.

L'approche dlopen peut s'avérer utile si vous n'avez besoin que du code partagé sur iOS 8. Si vous en avez besoin sur iOS 7, vous devez l'inclure dans la cible de l'application. Et une fois que vous faites cela, vous n’avez plus besoin du cadre. Vous pouvez toujours utiliser un cadre pour l'extension de l'application, mais cela n'est pas vraiment utile. Vous feriez le travail de création du cadre, mais n'en tiriez aucun avantage. Il suffit d'inclure le code partagé dans les deux cibles.

Et du guide d'extension d'Apple https://developer.Apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf

Si vous vous connectez à un framework intégré à partir de votre application contenante, vous pouvez toujours le déployer vers des versions d'iOS antérieures à 8.0, même si les frameworks intégrés ne sont pas disponibles dans ces versions.

12
BigCheesy

Approfondissement Documentation Apple J'ai découvert la commande dlopen , ==, qui permet de relier les bibliothèques de certains conditions, en fonction des versions du système et des bibliothèques prises en charge.

exemple d'utilisation de dlopen: La fonction 'dlopen ()' est-elle une API privée?

Alors regardons la solution fournie par Apple Docs:

Déploiement d'une application contenant sur les anciennes versions d'iOS

Si vous vous connectez à un framework intégré à partir de votre application contenante, vous pouvez toujours le déployer vers des versions d'iOS antérieures à 8.0, même si les frameworks intégrés ne sont pas disponibles dans ces versions.

Le mécanisme qui vous permet de le faire est la commande dlopen ==, que vous utilisez pour lier et charger conditionnellement un bundle de framework. Vous utilisez cette commande comme alternative au lien de compilation que vous pouvez spécifier dans l’éditeur Xcode General ou Build Phases. L'idée principale est de lier les frameworks intégrés à votre application contenant uniquement lors de l'exécution sous iOS 8.0 ou version ultérieure ].

Vous devez utiliser Objective-C, pas Swift, dans vos instructions de code qui chargent de manière conditionnelle un bundle de framework. Le reste de votre application peut être écrit dans l'une ou l'autre langue, et le cadre intégré lui-même peut également être écrit dans l'une ou l'autre langue.

Après avoir appelé dlopen , accédez aux classes de l'infrastructure intégrée à l'aide du type d'instruction suivant:

MyLoadedClass *loadedClass = [[NSClassFromString (@"MyClass") alloc] init];

IMPORTANT

Si votre cible d'application contenue est liée à une infrastructure intégrée, elle doit inclure l'architecture arm64, sinon l'application sera rejetée par l'App Store.

Pour configurer un projet Xcode d'extension d'application afin de tirer parti des liens conditionnels

  1. Pour chacune de vos extensions d'applications contenues, définissez la cible de déploiement sur iOS 8.0 ou version ultérieure, comme d'habitude. Faites-le dans la section "Informations de déploiement" de l'onglet Général de l'éditeur de cible Xcode.
  2. Pour votre application contenant, définissez la cible de déploiement sur la version la plus ancienne d'iOS que vous souhaitez prendre en charge.
  3. Dans votre application conteneur, conditionnez les appels à la commande dlopen au cours d'une exécution pour vérifier la version iOS à l'aide de la méthode systemVersion. Appelez la commande dlopen uniquement si votre application contenant s'exécute sous iOS 8.0 ou version ultérieure. Veillez à utiliser Objective-C et non Swift lors de cet appel.

Certaines API iOS utilisent des infrastructures intégrées via la commande dlopen. Vous devez conditionner votre utilisation de ces API comme vous le faites lorsque vous appelez directement dlopen . Ces API sont du type CFBundleRef opaque:

CFBundleGetFunctionPointerForName
CFBundleGetFunctionPointersforNames

Et de la classe NSBundle:

charge
loadAndReturnError:
classNamed:

Dans une application contenant que vous déployez sur des versions d'iOS antérieures à 8.0, appelez ces API uniquement dans le cadre d'une vérification de l'exécution garantissant que vous vous exécutez dans iOS 8.0 ou une version plus récente, et appelez ces API à l'aide d'Objective-C.

4
E-Riddie

Correction de l'erreur dans xcode 6.1.1

en utilisant vim ou vi, ouvrez le fichier project.pbxproj.

A la fin du fichier (recherche 8.1), il y aurait la section Begin XCBuildConfiguration

Cherchez votre cadre.

Dans les cas, même si la cible de déploiement était définie sur 7.1 via Xcode -> général dans les paramètres de la cible, l'entrée du fichier contenait la version 8.1 pour les versions debug et release.

Voici l'ancienne section de fichier qui ressemble à:

CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = ENFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VERSIONING_SYSTEM = "Apple-generic";
VERSION_INFO_PREFIX = "";

La nouvelle section ressemble à:

CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = ENFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VERSIONING_SYSTEM = "Apple-generic";
VERSION_INFO_PREFIX = "";

Maintenant, nous n'obtenons pas d'erreur mais juste un avertissement (mais cela fonctionne sur un périphérique iOS 7.1): ld: avertissement: les frameworks/dylibs intégrés ne fonctionnent que sur iOS 8 ou version ultérieure

Cela ressemble à un bogue xcode qui définit de manière incorrecte différentes cibles ios, puis provoque une erreur.

4
Gamma-Point

Pour info, j'ai eu ce problème lors du changement de projet d'un type de déploiement iOS8 à iOS7.

L'application utilisait des cocoapodes et aucun framework intégré personnalisé.

Je devais changer les deux objectifs principaux du projet
Application
Test d'application

Changer le type de Mach-O en statique (réponse ci-dessus).

Puis sur le projet cocoapods. Sous chaque projet de sous-pod, changez le type de Mach-O en statique, laissant le paramètre Mach-O du projet principal du pod à blanc.

2
StuartM

J'ai réglé le type Mach-O sur EXECUTABLE et cela a fonctionné pour moi. La définition sur Static, Dynamic ou Bundle a créé d’autres erreurs lors de l’exécution.

Cible> "Votre application"> Paramètres de construction> Liaison> Type Mach-O> Exécutable

2
ctw

Nous avons essayé d'exécuter le dernier code sur les configurations suivantes:

iOS 8+ - iPhone 5s iOS 7.1.2 - iPhone 4 iOS 6.1.3 - iPad 4

L'application fonctionne correctement sur les trois appareils, mais l'avertissement est présent dans le Xcode lors de la compilation. "Les dylibs/frameworks intégrés ne fonctionnent que sur iOS 8 ou supérieur"

De plus, j'ai essayé d'archiver l'application pour la soumettre à l'App Store.

En outre, vous avez découvert un lien où Apple a déclaré qu'il s'agissait d'un bogue https://devforums.Apple.com/message/999579#999579 =

2
Ravi Dalmia

Je résous ce problème de la manière suivante: tilisez la même cible de déploiement dans les cibles "Cadre intégré" et "Application principale".

1
Payal Maniyar

Donc, temporaire, j'ai dit non à la bibliothèque dynamique, alors que de nombreux périphériques sur iOS 7. Comment j'ai résolu mon problème. J'avais besoin de lib pour transférer le modèle entre l'application et l'extension. Donc, j'ai mis mon modèle en chaîne JSON dans un conteneur partagé. Et cela fonctionne comme un charme.

1
Andrey Gagan

Je rencontrais un problème dans lequel j’avais besoin d’inclure certaines bibliothèques en tant qu’infrastructures intégrées, sinon j’ai reçu l’erreur ci-dessus et, ce faisant, j’ai reçu des erreurs lors de la soumission à l’app store.

Ma solution consistait à utiliser des pods et à vous assurer de ne pas commenter le "use_frameworks!" ligne.

0
Jason Silver

J'ai eu un bug lors de la mise à jour vers xcode 7.3. Et j'avais une solution pour moi. - Projet de modification des cibles dans les modules -> 7.0 - J'espère que c'est utile! attack

0
PhuocLuong

Supprimez les cadres d'utilisation! depuis votre fichier PodFile si vous souhaitez que la structure fonctionne dans iOS 7.0. c.-à-d. exécuter la commande de désintégration du pod, modifier votre PodFile puis réexécuter la commande d'installation du pod

De plus, après cela, j'ai dû ajouter tous les fichiers .h du Framework dans le fichier Bridging, ce qui a résolu le problème. Supprimez également l’importation de la bibliothèque TestLibrary des fichiers Swift

0
Sohil Dedhia

Lorsque vous utilisez une bibliothèque dynamique sur ios, vous devez signer la bibliothèque avec un code. Dans le Xcode 6, vous devez sélectionner le "Code Sign On Copy". Et avec le Xcode5, vous devez signer la bibliothèque par vous-même avec un script d'exécution. comme :

LOCATION="${BUILT_PRODUCTS_DIR}"/"${FRAMEWORKS_FOLDER_PATH}"
IDENTITY="iPhone Developer: xxxxx"
codesign --verbose --force --sign "$IDENTITY" "$LOCATION/BeeFramework.framework/BeeFramework"
0
iOkay