Tenho visto muitos desenvolvedores que adicionam várias macros de conveniência ao Prefix.pch de seus projetos iOS.
O que você recomenda (ou não) adicionar ao arquivo iOS Prefix.pch? Qual é a aparência do seu Prefix.pch?
Tenho visto muitos desenvolvedores que adicionam várias macros de conveniência ao Prefix.pch de seus projetos iOS.
O que você recomenda (ou não) adicionar ao arquivo iOS Prefix.pch? Qual é a aparência do seu Prefix.pch?
Macros.h
, e importe esse arquivo para o seu prefix.pch
.
Respostas:
Ewww… não coloque macros em um arquivo .pch! Um arquivo .pch é, por definição, um cabeçalho pré-compilado específico do projeto. Realmente não deve ser usado fora do contexto do projeto e realmente não deve conter nada além de #include
s e #import
s.
Se você tiver algumas macros e outras que deseja compartilhar entre os cabeçalhos, coloque-as em um arquivo de cabeçalho próprio - Common.h
ou qualquer outra coisa - e #include
isso no início do .pch.
Para iOS e OS X modernos, as pessoas deveriam usar Módulos . Isso é habilitado por padrão para novos projetos, e a importação / inclusão é realizada usando@import
.
Os módulos permitem que o compilador crie uma representação intermediária do conteúdo de um módulo (por exemplo, os cabeçalhos de um framework). Muito parecido com um PCH, esta representação intermediária pode ser compartilhada entre várias traduções. Mas os módulos vão além porque um módulo não é necessariamente específico de destino e suas declarações não precisam ser localizadas (para a *.pch
). Esta representação pode economizar uma tonelada de trabalho de compilador redundante.
Usando módulos, você não precisa de um PCH e provavelmente deveria simplesmente eliminá-los completamente - em favor de usar o @import
local para a dependência. Nesse caso, um PCH está apenas evitando que você digite inclusões locais para dependências (o que, IMO, você deve fazer de qualquer maneira).
Agora, se olharmos para trás para a pergunta original: você deve evitar encher seu PCH com todo tipo de coisas aleatórias; Macros, constantes #defines
e todos os tipos de pequenas bibliotecas. Geralmente, você deve omitir o que realmente é desnecessário para a maioria dos arquivos de origem . Colocar todos os tipos de coisas em seu PCH é apenas adicionar um monte de peso e dependência. Vejo que as pessoas colocam tudo o que têm link e mais no PCH. Na realidade, estruturas auxiliares normalmente só precisam ser visíveis para algumas traduções na maioria dos casos. Por exemplo, "Aqui está o nosso material do StoreKit - vamos importar o StoreKit apenas para onde ele deveSeja visível. Especificamente, essas 3 traduções ". Isso mantém seus tempos de compilação baixos e ajuda a controlar suas dependências, para que você possa reutilizar o código mais facilmente. Portanto, em um projeto ObjC, você normalmente pararia na Fundação. Se houver muito de IU, então você pode considerar adicionar UIKit ou AppKit ao seu PCH. Isso tudo pressupõe que você deseja otimizar os tempos de compilação. Um dos problemas com grandes PCHs que incluem (quase) tudo é que a remoção de dependências desnecessárias consome muito tempo. as dependências do seu projeto aumentam e os tempos de construção aumentam, você precisa revidar eliminando dependências desnecessárias para reduzir os tempos de construção. Além disso, qualquer coisa que mude com frequência geralmente deve ser mantida fora do seu PCH. Uma mudança requer uma reconstrução completa. Existem algumas opções para compartilhar PCHs. Se você usar PCHs,
Quanto ao que coloquei no meu PCH: parei de usá-los para a grande maioria dos alvos anos atrás. Geralmente, não há o suficiente em comum para se qualificar. Tenha em mente que eu escrevo C ++, ObjC, ObjC ++ e C - o compilador emite um para cada idioma em seu destino. Portanto, habilitá-los geralmente resultava em tempos de compilação mais lentos e maior I / O. Em última análise, aumentar a dependência não é uma boa maneira de combater a dependência em projetos complexos. Trabalhando com vários idiomas / dialetos, há muitas variações nas dependências necessárias para um determinado destino. Não, eu não recomendaria isso como ideal para todos os projetos, mas isso dá alguma perspectiva para o gerenciamento de dependências em projetos maiores.
Referências
Notas
#import "MyLib/MyLib.h"
. Sempre que um arquivo incluído por MyLib.h
alterações, todos os arquivos de origem no aplicativo devem ser recompilados. Se você usar o MyLib em apenas um arquivo de origem, apenas esse arquivo deverá ser recompilado quando o MyLib for alterado. Acredite ou não, não estou usando nenhum arquivo PCH atualmente.
Eu concordo com o bbum. Minha opinião sobre o arquivo PCH é que ele deve conter praticamente apenas instruções #include
ou #import
. Então se você tem um monte de votos, macros de alto nível, defini-los em algo como Common.h
e #import
esse arquivo, como bbum sugeriu.
Eu costumo dar um passo adiante e usar o arquivo PCH para #import
um arquivo chamado XXCategories.h
(onde XX
é a classe convenção de nomenclatura prefixo que você usa) que contém #import
s para todas as categorias minha UIKit e de classe Foundation: NSString+XXAdditions.h
, UIColor+XXAdditons.h
, etc.
#import
e apenas importá-los #import
diretamente? Não seriam iguais? Ou isso afeta o desempenho?
#import
e #include
.
crie um arquivo de cabeçalho "macros.h"
importe este cabeçalho para Prefix.pch
Neste macros.h coloque todas as estruturas e outras coisas importantes.
Se você está preocupado com o desempenho, não se preocupe, veja o que a apple diz:
Cabeçalhos e desempenho
Se você está preocupado com o fato de que incluir um arquivo de cabeçalho mestre pode fazer com que seu programa inche, não se preocupe. Como as interfaces do OS X são implementadas usando estruturas, o código para essas interfaces reside em uma biblioteca compartilhada dinâmica e não em seu executável. Além disso, apenas o código usado por seu programa é carregado na memória em tempo de execução, portanto, seu espaço na memória permanece pequeno. Quanto a incluir um grande número de arquivos de cabeçalho durante a compilação, mais uma vez, não se preocupe. O Xcode fornece um recurso de cabeçalho pré-compilado para acelerar os tempos de compilação. Compilando todos os cabeçalhos da estrutura de uma vez, não há necessidade de recompilar os cabeçalhos, a menos que você adicione uma nova estrutura. Enquanto isso, você pode usar qualquer interface das estruturas incluídas com pouca ou nenhuma penalidade de desempenho.
também em minhas macros.h coloquei várias constantes como:
// 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__ )
... para executar blocos no tópico principal:async(^{ self.someLabel.text = @":D"; });