J'ai vu de nombreux développeurs ajouter diverses macros pratiques au fichier Prefix.pch de leurs projets iOS.
Que recommandez-vous d'ajouter (ou de ne pas ajouter) au fichier Prefix.pch d'iOS ? À quoi ressemble votre Prefix.pch ?
J'ai vu de nombreux développeurs ajouter diverses macros pratiques au fichier Prefix.pch de leurs projets iOS.
Que recommandez-vous d'ajouter (ou de ne pas ajouter) au fichier Prefix.pch d'iOS ? À quoi ressemble votre Prefix.pch ?
Beurk ... ne mettez pas de macros dans un fichier .pch! Un fichier .pch est, par définition, un en-tête précompilé spécifique au projet. Il ne devrait vraiment pas être utilisé en dehors du contexte du projet et il ne devrait vraiment contenir rien d'autre que des #include
et des #import
.
Si vous avez des macros et autres que vous voulez partager entre les en-têtes, alors mettez-les dans un fichier d'en-tête séparé - Common.h
ou autre chose - et #include
celui-ci au début du .pch.
Pour les versions modernes d'iOS et d'OS X, les gens devraient utiliser Modules. Cela est activé par défaut pour les nouveaux projets, et l'importation/l'inclusion se fait en utilisant @import
.
Les modules permettent au compilateur de créer une représentation intermédiaire du contenu d'un module (par exemple, les en-têtes d'un framework). Tout comme un PCH, cette représentation intermédiaire peut être partagée entre plusieurs traductions. Mais les modules vont plus loin car un module n'est pas nécessairement spécifique à une cible, et leurs déclarations n'ont pas besoin d'être localisées (dans un *.pch
). Cette représentation peut vous faire économiser beaucoup de travail redondant pour le compilateur.
En utilisant les modules, vous n'avez pas besoin d'un PCH, et vous devriez probablement vous en débarrasser entièrement - au profit de l'utilisation de @import
local à la dépendance. Dans ce cas, un PCH ne vous sauve que du bourrage des inclusion locales aux dépendances (ce que vous devriez faire de toute façon selon moi).
Maintenant, si nous revenons à la question d'origine : Vous devez éviter de remplir votre PCH avec toutes sortes de choses aléatoires ; Macros, constantes, #defines
, et toutes sortes de petites bibliothèques. Généralement, vous devriez omettre ce qui est vraiment inutile pour la majorité de vos fichiers source. Mettre toutes sortes de choses dans votre PCH revient simplement à ajouter beaucoup de poids et de dépendances. Je vois des gens mettre tout ce qu'ils lient et plus encore dans le PCH. En réalité, les frameworks auxiliaires ont généralement seulement besoin d'être visibles pour quelques traductions dans la plupart des cas. Par exemple, "Voici nos trucs StoreKit - importons StoreKit uniquement là où il le doit être visible. Spécifiquement, ces 3 traductions". Cela réduit vos temps de construction et vous aide à suivre vos dépendances, vous permettant ainsi de réutiliser le code plus facilement. Donc, dans un projet ObjC, vous vous arrêteriez généralement à Foundation. S'il y a beaucoup d'UI, alors vous pourriez envisager d'ajouter UIKit ou AppKit à votre PCH. Tout ceci suppose que vous souhaitez optimiser les temps de construction. L'un des problèmes avec les grands PCHs qui incluent (presque) tout est que l'élimination des dépendances inutiles est très chronophage. Lorsque les dépendances de votre projet augmentent et que vos temps de construction augmentent, vous devez réagir en éliminant les dépendances inutiles afin de réduire vos temps de construction. De plus, tout ce qui change souvent doit en général être tenu à l'écart de votre PCH. Un changement nécessite une reconstruction complète. Il existe des options pour partager les PCHs. Si vous utilisez des PCHs, visez à les partager.
En ce qui concerne ce que je mets dans mon PCH : J'ai arrêté de les utiliser pour la grande majorité des cibles il y a des années. Il n'y a généralement pas suffisamment en commun pour les qualif ier. Gardez à l'esprit que j'écris du C++, de l'ObjC, de l'ObjC++ et du C - le compilateur en émet un pour chaque langage dans votre cible. Les activer entraînaient souvent des temps de compilation plus lents et une E/S plus élevée. En fin de compte, augmenter les dépendances n'est pas une bonne manière de lutter contre les dépendances dans des projets complexes. Travailler avec plusieurs langages/dialectes demande beaucoup de variations dans les dépendances requises pour une cible donnée. Non, je ne recommanderais pas cela comme étant optimal pour chaque projet, mais cela donne une certaine perspective sur la gestion des dépendances dans des projets plus importants.
Références
Notes
Je suis d'accord avec bbum. Mon avis sur le fichier PCH est qu'il devrait contenir à peu près seulement des déclarations #include
ou #import
. Donc si vous avez un tas de macros utiles de haut niveau, définissez-les dans quelque chose comme Common.h
et #import
ez ce fichier, comme l'a suggéré bbum.
Je vais généralement plus loin et j'utilise le fichier PCH pour #import
er un fichier appelé XXCategories.h
(où XX
est la convention de préfixe de nom de classe que vous utilisez) qui contient des #import
s pour toutes mes catégories de classe UIKit et Foundation : NSString+XXAdditions.h
, UIColor+XXAdditons.h
, etc.
Créez un fichier d'en-tête "macros.h"
Importez cet en-tête dans Prefix.pch
Dans ce macros.h, mettez tous les frameworks et autres éléments importants.
Si vous vous inquiétez des performances, ne vous inquiétez pas, regardez ce qu'Apple dit:
En-têtes et Performances
Si vous craignez qu'inclure un fichier d'en-tête principal puisse faire gonfler votre programme, ne vous inquiétez pas. Comme les interfaces OS X sont implémentées à l'aide de frameworks, le code de ces interfaces réside dans une bibliothèque partagée dynamique et non dans votre exécutable. De plus, seul le code utilisé par votre programme est jamais chargé en mémoire à l'exécution, de sorte que votre empreinte en mémoire reste également petite. Quant à l'inclusion d'un grand nombre de fichiers d'en-tête pendant la compilation, une fois de plus, ne vous inquiétez pas. Xcode offre une fonctionnalité d'en-tête précompilé pour accélérer les temps de compilation. En compilant tous les en-têtes de framework en une seule fois, il n'est pas nécessaire de recompiler les en-têtes à moins que vous n'ajoutiez un nouveau framework. Entre-temps, vous pouvez utiliser n'importe quelle interface des frameworks inclus avec peu ou pas de pénalité de performance.
aussi dans mon macros.h, je mets beaucoup de constantes comme:
// delegate
#define UIAppDelegate (AppDelegate *)[[UIApplication sharedApplication] delegate]
#define APPDELEGATE ((AppDelegate *)[[UIApplication sharedApplication] delegate])
// système
#define IS_IPHONE_4INCH (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height==568)
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
// taille de l'écran
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_4 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 480.0)
#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6PLUS (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0)
#define IS_RETINA_DISPLAY ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))
#define IS_PORTRAIT UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])
#define IS_LANDSCAPE UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])
//version du système
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
// mathématiques
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))
// couleurs
#define RGB(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define RGBA(r,g,b,a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:a]
#define MAKECOLOR(R, G, B, A) [UIColor colorWithRed:((float)R/255.0f) green:((float)G/255.0f) blue:((float)B/255.0f) alpha:A]
#define MAKECOLORFROMHEX(hexValue) [UIColor colorWithRed: ((float)((hexValue & 0xFF0000) >> 16))/255.0 green:((float)((hexValue & 0xFF00) >> 8))/255.0 blue:((float)(hexValue & 0xFF))/255.0 alpha:1.0]
//personnalisations
#define SHOW_STATUS_BAR [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
#define HIDE_STATUS_BAR [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
#define SHOW_NAVIGATION_BAR [self.navigationController setNavigationBarHidden:FALSE];
#define HIDE_NAVIGATION_BAR [self.navigationController setNavigationBarHidden:TRUE];
#define VC_OBJ(x) [[x alloc] init]
#define VC_OBJ_WITH_NIB(x) [[x alloc] initWithNibName : (NSString *)CFSTR(#x) bundle : nil]
#define RESIGN_KEYBOARD [[[UIApplication sharedApplication] keyWindow] endEditing:YES];
#define CLEAR_NOTIFICATION_BADGE [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
#define REGISTER_APPLICATION_FOR_NOTIFICATION_SERVICE [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)]
#define HIDE_NETWORK_ACTIVITY_INDICATOR [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
#define SHOW_NETWORK_ACTIVITY_INDICATOR [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.