Ho visto molti sviluppatori che aggiungono varie macro di convenienza al Prefix.pch dei loro progetti iOS.
Cosa consigli (o non) di aggiungere al file Prefix.pch di iOS? Che aspetto ha il tuo Prefix.pch?
Ho visto molti sviluppatori che aggiungono varie macro di convenienza al Prefix.pch dei loro progetti iOS.
Cosa consigli (o non) di aggiungere al file Prefix.pch di iOS? Che aspetto ha il tuo Prefix.pch?
Macros.h
, e poi importa questo file nel tuo prefix.pch
.
Risposte:
Ewww… non mettere le macro in un file .pch! Un file .pch è, per definizione, un'intestazione precompilata specifica del progetto. In realtà non dovrebbe essere utilizzato al di fuori del contesto del progetto e in realtà non dovrebbe contenere nient'altro che #include
s e #import
s.
Se hai alcune macro e tali da condividere tra le intestazioni, inseriscile in un loro file di intestazione - Common.h
o qualsiasi altra cosa - e #include
quello all'inizio del .pch.
Per iOS e OS X moderni, le persone dovrebbero utilizzare i moduli . Questa opzione è abilitata per impostazione predefinita per i nuovi progetti e l'importazione / inclusione viene eseguita utilizzando @import
.
I moduli consentono al compilatore di creare una rappresentazione intermedia del contenuto di un modulo (ad esempio gli header di un framework). Proprio come un PCH, questa rappresentazione intermedia può essere condivisa tra più traduzioni. Ma i moduli fanno un ulteriore passo avanti perché un modulo non è necessariamente specifico per la destinazione e le loro dichiarazioni non devono essere localizzate (in a *.pch
). Questa rappresentazione può farti risparmiare un sacco di lavoro ridondante del compilatore.
Usando i moduli, non hai bisogno di un PCH e probabilmente dovresti semplicemente eliminarli del tutto, a favore dell'uso @import
locale alla dipendenza. In tal caso, un PCH ti evita solo di digitare inclusioni locali alle dipendenze (cosa che IMO dovresti fare comunque).
Ora, se guardiamo indietro alla domanda originale: dovresti evitare di riempire il tuo PCH con ogni sorta di cose casuali; Macro, costanti #defines
e ogni sorta di piccole librerie. In generale, dovresti omettere ciò che è veramente non necessario per la maggior parte dei tuoi file sorgente . Mettere ogni sorta di cose nel tuo PCH significa solo aggiungere un po 'di peso e dipendenza. Vedo che le persone inseriscono tutto ciò a cui collegano e altro ancora nel PCH. In realtà, i framework ausiliari in genere devono essere visibili solo a poche traduzioni nella maggior parte dei casi. Ad esempio "Ecco il nostro materiale per StoreKit: importiamo StoreKit solo dove deveessere visibile. In particolare, queste 3 traduzioni ". Ciò riduce i tempi di compilazione e ti aiuta a tenere traccia delle tue dipendenze, in modo da poter riutilizzare il codice più facilmente. Quindi in un progetto ObjC, di solito ti fermi alla Foundation. Se c'è molto dell'interfaccia utente, potresti prendere in considerazione l'aggiunta di UIKit o AppKit al tuo PCH. Tutto questo presuppone che tu voglia ottimizzare i tempi di compilazione. Uno dei problemi con i PCH di grandi dimensioni che includono (quasi) tutto è che la rimozione delle dipendenze non necessarie richiede molto tempo. Una volta le dipendenze del tuo progetto crescono ei tuoi tempi di compilazione aumentano, devi reagire eliminando le dipendenze non necessarie per ridurre i tempi di compilazione. Inoltre, tutto ciò che cambia spesso dovrebbe generalmente essere tenuto fuori dal tuo PCH. Una modifica richiede una ricostruzione completa. Ci sono alcune opzioni per condividere i PCH. Se utilizzi i PCH,
Per quanto riguarda quello che ho inserito nel mio PCH: ho smesso di usarli per la stragrande maggioranza degli obiettivi anni fa. Di solito non c'è abbastanza in comune per qualificarsi. Ricorda, scrivo C ++, ObjC, ObjC ++ e C - il compilatore ne emette uno per ogni lang nel tuo target. Quindi abilitarli spesso si traduceva in tempi di compilazione più lenti e I / O più elevati. In definitiva, aumentare la dipendenza non è un buon modo per combattere la dipendenza in progetti complessi. Lavorando con più lingue / dialetti, ci sono molte variazioni nelle dipendenze richieste per un dato target. No, non lo consiglierei come ottimale per ogni progetto, ma questo dà una prospettiva alla gestione delle dipendenze in progetti più grandi.
Riferimenti
Appunti
#import "MyLib/MyLib.h"
. Ogni volta che un file viene incluso dalle MyLib.h
modifiche, ogni file sorgente nell'app deve essere ricompilato. Se utilizzi MyLib in un solo file sorgente, solo quel file deve essere ricompilato quando MyLib cambia. Che ci crediate o no, non sto usando alcun file PCH in questi giorni.
Sono d'accordo con bbum. La mia opinione sul file PCH è che dovrebbe contenere praticamente solo #include
o #import
dichiarazioni. Quindi, se hai un sacco di macro utili e di alto livello, definiscili in qualcosa come Common.h
e #import
quel file, come suggerito da bbum.
Io di solito andare un ulteriore passo avanti e utilizzare il file PCH ad #import
un file chiamato XXCategories.h
(dove XX
è la convenzione di denominazione prefisso di classe si utilizza) che contiene #import
s per tutte le categorie il mio UIKit e di classe Fondazione: NSString+XXAdditions.h
, UIColor+XXAdditons.h
, etc.
#import
e importarli #import
direttamente? Non sarebbero la stessa cosa? O influisce sulle prestazioni?
#import
e #include
.
creare un file di intestazione "macros.h"
importa questa intestazione in Prefix.pch
In questo macros.h metti tutti i framework e altre cose importanti.
Se sei preoccupato per le prestazioni, non preoccuparti, guarda cosa dice Apple:
Intestazioni e prestazioni
Se sei preoccupato che l'inclusione di un file di intestazione principale possa far gonfiare il tuo programma, non preoccuparti. Poiché le interfacce OS X vengono implementate utilizzando framework, il codice per tali interfacce risiede in una libreria condivisa dinamica e non nel tuo eseguibile. Inoltre, solo il codice utilizzato dal programma viene caricato in memoria in fase di runtime, quindi anche il footprint in memoria rimane piccolo. Per quanto riguarda l'inclusione di un gran numero di file di intestazione durante la compilazione, ancora una volta, non preoccuparti. Xcode fornisce una funzione di intestazione precompilata per accelerare i tempi di compilazione. Compilando tutte le intestazioni del framework contemporaneamente, non è necessario ricompilare le intestazioni a meno che non si aggiunga un nuovo framework. Nel frattempo, puoi utilizzare qualsiasi interfaccia dai framework inclusi con poca o nessuna penalizzazione delle prestazioni.
anche nel mio macro.h metto molte costanti come:
// delegate
#define UIAppDelegate (AppDelegate *)[[UIApplication sharedApplication] delegate]
#define APPDELEGATE ((AppDelegate *)[[UIApplication sharedApplication] delegate])
// system
#define IS_IPHONE_4INCH (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height==568)
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
// screen size
#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])
//system version
#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
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
#define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))
// cores
#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]
//customizations
#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];
#define async(...) dispatch_async(dispatch_get_main_queue(), __VA_ARGS__ )
... per eseguire blocchi sul thread principale:async(^{ self.someLabel.text = @":D"; });