web-dev-qa-db-fra.com

Comment ajouter un cadre dans un autre cadre (Cadre Umbrella)

J'ai construit un cadre en utilisant le tutoriel suivant .

Et j'ai aussi obtenu this framework.

J'essaie d'implémenter le second Framework à l'intérieur du mien, d'après ce que j'ai lu dans Apple), le framework résultant est appelé "Umbrella Framework".

J'ai ajouté le second framework dans le framework en utilisant le glisser-déposer et en vérifiant qu'il se trouve dans "Link Binary With Libraries".

Et après j'ai essayé de faire la prochaine importation dans l'une des classes de la structure my:

#import <CrashReporter/CrashReporter.h>

J'ai reçu une erreur car le cadre importé n'est pas visible.

J'ai aussi vu le message stackoverflow: Comment créer un framework parapluie dans iOS SDK?

Mise à jour

Quelqu'un a-t-il essayé d'extraire les classes PLCrashReporter pour iOS et de les intégrer dans un projet?

Vous pouvez trouver ma tentative ici .

43
Laur Stefan

La tentation de distribuer un autre cadre est compréhensible, mais fortement découragée. Je vais essayer d’expliquer pourquoi (avec des arguments) et de vous proposer d’excellentes alternatives qui vous aideront dans votre cas.

Les frameworks Umbrella sont destinés à être utilisés. Lorsque vous êtes le distributeur de ces deux frameworks, vous en avez le plein contrôle et ils seront distribués ensemble.

Il existe une citation populaire sur le sujet chez Apple, dans laquelle ils disent qu'ils découragent les frameworks parapluies.

Ne créez pas de cadres de parapluies

Bien qu'il soit possible de créer des frameworks multiples à l'aide de Xcode, cela est inutile pour la plupart des développeurs et n'est pas recommandé. Apple utilise des frameworks parapluies pour masquer certaines interdépendances entre les bibliothèques du système d'exploitation. Dans presque tous les cas, vous devriez pouvoir inclure votre code dans un seul bundle de framework standard. Sinon, si votre code étant suffisamment modulaire, vous pouvez créer plusieurs frameworks, mais dans ce cas, les dépendances entre modules seraient minimes ou inexistantes et ne devraient pas garantir la création d'un parapluie pour eux.

Premièrement, voici ce que la plupart des développeurs font dans cette situation, car de nombreux frameworks reposent sur d’autres.

Informez l'utilisateur que votre infrastructure nécessite l'utilisation d'une infrastructure tierce. Ceci est complètement standard et prévu dans la plupart des cas. Puis reliez-le au niveau du système. C'est aussi simple que ça. Votre framework trouvera la tierce partie et sa fonction comme si vous utilisiez un framework natif. Prenez UIKit par exemple. Pour créer un lien vers le tiers, suivez les étapes décrites dans la section suivante. Cela peut certes être fait de manière classique, mais utiliser un outil tel que CocoaPods facilitera la maintenance de votre projet.

Répondre complètement à votre question, au lieu d'ajouter le framework tiers de la manière habituelle, vous risqueriez de rencontrer des problèmes et complications, utilisez CocoaPods pour l’ajouter pour vous. De cette façon, vous éliminez les éventuels problèmes et bénéficiez également de CocoaPods, qui vous fournit la version exacte du tiers requis.

Voici le fichier Podfile CocoaPods pour une application appelée "CrashTest"

target 'CrashTest' do
pod 'PLCrashReporter', '~> 1.2.0'
end

Juste pour clarifier, lorsque vous développez le cadre, il sera toujours ajouté à votre projet et visible. La grande différence ici réside dans le fait qu'il sera distribué séparément de votre infrastructure et que les utilisateurs finaux devront ajouter les deux à leurs projets pour que tout fonctionne correctement.

Voici les raisons pour lesquelles cela est fait de cette façon.

Par exemple, vous voudriez inclure PLCrashReporter dans votre framework. Supposons qu'un autre fournisseur de framework souhaite l'inclure également dans le leur. L'application utilisant les deux frameworks aura PLCrashReporter incluse deux fois (dans le cadre de chaque framework parapluie). Possible même différentes versions de celui-ci. Cela pourrait entraîner de graves problèmes au sein de l'application utilisateur. Comme décrit dans la section précédente, si les deux frameworks sont liés à PLCrashReporter, ce problème serait complètement évité.

Un autre point que j'ai évoqué ci-dessus est le contrôle de version. Lors de la distribution d'un framework parapluie, vous devez pouvoir contrôler les versions de tous les frameworks impliqués et vous n'avez aucun contrôle sur le framework tiers. Ce qui conduirait à nouveau à un problème similaire à celui décrit ci-dessus.

Je sais que cette approche ne fournit pas de réponse directe à la question, mais tente plutôt de décourager une mauvaise pratique, tout en indiquant la manière habituelle de faire les choses.

51
Vel Genov

Apple vous déconseille de créer un framework parapluie, mais affirme néanmoins que cela est possible avec ne description de sa structure, etc. , donc je vais me concentrer sur la façon de le faire.

Je dois mentionner que si vous contrôlez un ou plusieurs frameworks, les regrouper dans un seul n'est pas une si mauvaise idée et peut aider le développeur final.

Créer un framework parapluie est vraiment simple maintenant sur les Xcodes récents (7 et plus)

Voici comment le faire.

Commencez par créer un cadre:

enter image description here

Traîne CrashReporter.framework au projet cadre Umbrella:

enter image description here

Exemple de code pour vous assurer que les deux frameworks sont fonctionnels:

Umbrella.h:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@interface Umbrella : NSObject

+(void)sayHelloFromUmbrella;

@end

Umbrella.m:

#import "Umbrella.h"
#import <CrashReporter/CrashReporter.h>

@implementation Umbrella

+(void)sayHelloFromUmbrella
{
    NSLog(@"Hey from Umbrella");
    PLCrashReporter *crashObject = [[PLCrashReporter alloc]initWithConfiguration:nil];
    NSLog(@"crashObject: %@",crashObject);
}

@end

Construisez et vous aurez le Umbrella.framework (cela contient CrashReporter.framework) dans votre dossier de construction.

Traîne Umbrella.framework et placez-le dans "Binaires incorporés" dans le projet qui va l'utiliser:

enter image description here

Ensuite, importez simplement votre cadre fini.

ViewController.m du projet que nous venons de faire glisser Umbrella.framework vers :

#import "ViewController.h"
#import <Umbrella/Umbrella.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [Umbrella sayHelloFromUmbrella];
}

Ce qui produira ceci:

Hey from Umbrella 
crashObject: <PLCrashReporter: 0x7fb441d5c650>

Ce qui nous dit que les deux cadres fonctionnent.

26
Segev

ICI IS UN PROJET DE DEMO:

Démo du framework Umbrella

Toutes les réponses sous cette ligne sont fausses, car elles font juste ce qui copie manuellement les sous-cadres dans "cadre général"

Intégration d'un framework dans un framework (iOS 8 +)

Comment créer un framework parapluie dans un SDK iOS?

Comment ajouter un cadre dans un autre cadre (Cadre Umbrella)

cadre de parapluie

La première chose à savoir est que le "parapluie" est une conception sous Mac OS et non sous iOS, le document officiel est ici

https://developer.Apple.com/library/content/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/CreationGuidelines.html#//Apple_ref/doc/uid/20002254-BAJHGGGA

si vous voulez créer un "UmbrellaFramework" non recommandé, vous devez suivre ces étapes étape par étape et connaître les détails lors de la compilation et des périodes de liens.

  1. Changer tous les sous-frameworks Mach-O en bibliothèque statique, cela signifie compiler cette cible en tant que bibliothèque statique (.a)
  2. Copiez manuellement tous les sous-cadres dans UmbrellaFramework pendant la phase de construction (comme le faisaient les autres réponses)
  3. Ajoutez "FakeBundleShellScript" à la cible "UmbrellaFramework", tous les sous-cadres se conditionnant comme ressources permettant de rejoindre "UmbrellaFramework".
  4. Changez la fonction de chargement du framework, vous devez charger les ressources du sous-framework via chemin ou url, car il est devenu un paquet, cette étape signifie que vous devez avoir le contrôle suprême de tous les codes des sous-frameworks et du parapluie.

!! Voici un exemple de "FakeBundleShellScript" vous pouvez vous référer

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
BUNDLE_IN_ROOT="$APP_PATH/${FRAMEWORK_EXECUTABLE_NAME}.bundle"
if [[ -e "$FRAMEWORK_EXECUTABLE_PATH" ]]; then
  FRAMEWORK_MACH_O="$(otool -a "$FRAMEWORK_EXECUTABLE_PATH" | head -n 1)"
  FRAMEWORK_FAT_Arch="$(lipo -info "$FRAMEWORK_EXECUTABLE_PATH")"
else
  FRAMEWORK_MACH_O="NO EXIST"
  FRAMEWORK_FAT_Arch="NO EXIST"
fi
echo "FRAMEWORK_EXECUTABLE_NAME is $FRAMEWORK_EXECUTABLE_NAME"
echo "FRAMEWORK_EXECUTABLE_PATH is $FRAMEWORK_EXECUTABLE_PATH"
echo "FRAMEWORK_MACH_O is $FRAMEWORK_MACH_O"
echo "FRAMEWORK_FAT_Arch is $FRAMEWORK_FAT_Arch"
echo "BUNDLE_IN_ROOT is $BUNDLE_IN_ROOT"
if [[ "$FRAMEWORK_MACH_O" =~ "Archive :" ]]; then
  echo "Rmove Static-Mach-O is $FRAMEWORK_EXECUTABLE_PATH"
  rm "$FRAMEWORK_EXECUTABLE_PATH"
  defaults write "$FRAMEWORK/Info.plist" CFBundlePackageType "BNDL"
  defaults delete "$FRAMEWORK/Info.plist" CFBundleExecutable
  if [[ -d "$BUNDLE_IN_ROOT" ]]; then
    rm -rf "$BUNDLE_IN_ROOT"
  fi
  mv -f "$FRAMEWORK" "$BUNDLE_IN_ROOT"
Elif [[ "$FRAMEWORK_FAT_Arch" =~ "Architectures in the fat file" ]]; then
  #statements
  EXTRACTED_ARCHS=()
  for Arch in $ARCHS
  do
    echo "Extracting $Arch from $FRAMEWORK_EXECUTABLE_NAME"
    lipo -extract "$Arch" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$Arch"
    EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$Arch")
  done
  echo "Merging extracted architectures: ${ARCHS}"
  lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
  rm "${EXTRACTED_ARCHS[@]}"
  echo "Replacing original executable with thinned version"
  rm "$FRAMEWORK_EXECUTABLE_PATH"
  mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
fi
done

http://alanli7991.github.io/2017/07/17/%E6%A8%A1%E5%9D%97%E5%8C%9617Framework%E4%B8%8EStaticFramework%E4%BC%AA % E8% A3% 85Bundle /

Comme tout ce que j'ai dit, le point clé pour faire un "UmbrellaFramework" non recommandé est !!! [Compilez les sous-cadres en tant que statiques, traitez les ressources via un paquet factice], N'OUBLIEZ PAS !! Apple a toujours dit NE PAS CRÉER UN UmbrellaFramework

si vous comprenez le chinois, vous pouvez obtenir plus de détails pour créer un "cadre de parapluie" sur mon blog

Alan.li 2017 的 文章

13
MinamiTouma

J'ai essayé de faire ce que @Segev avait suggéré, mais j'ai continué à recevoir l'erreur selon laquelle les fichiers de la structure intégrée étaient manquants.

Cependant, en faisant quelques config supplémentaires, j'ai réussi à le faire fonctionner!

Voici ce que j'ai fait:

  1. Ajoutez le fichier d'en-tête de la structure intégrée dans le projet de structure de parapluie.
  2. Dans l'en-tête de parapluie, ajoutez: importer "EmbeddedFramework.h"
  3. Importez ensuite le framework parapluie dans le projet souhaité et vous n'aurez plus d'erreur

Vous verrez que le dossier "En-têtes" du framework parapluie comprendra le fichier "EmbeddedFramework.h".

Vous pouvez voir un exemple de projet ici:

J'espère que cela t'aides

5
Adriana Pineda