iOS Prefix.pch最佳做法

我见过许多开发人员将各种便利的macros添加到他们的iOS项目的Prefix.pch中。

什么(或不),你build议添加到iOS Prefix.pch文件? 你的Prefix.pch是什么样的?

Ewww …不要把macros放在.pch文件中! 根据定义,.pch文件是项目特定的预编译头文件。 它确实不应该在项目的上下文之外使用,它实际上不应该包含任何东西,但#include s和#import s。

如果你有一些macros,并希望在头文件之间共享,那么把它们粘贴在它们自己的头文件Common.h或者包含在.pch开头的#include。

对于现代的iOS和OS X,人们应该使用模块 。 这对新项目是默认启用的,导入/包含是使用@import完成的。

模块允许编译器创build模块内容的中间表示(例如框架的头文件)。 就像一个PCH,这个中间表示可以在多个翻译中共享。 但模块更进一步,因为一个模块不一定是特定的目标,他们的声明不需要本地化( *.pch )。 这种表示方式可以为您节省大量的冗余编译器工作

使用模块,你不需要一个PCH,你可能应该完全消除它们 – 有利于使用@import local来依赖。 在这种情况下,PCH只会让你不能从包含本地属性到依赖项(你应该这样做)。

现在,如果我们回顾一下原来的问题:你应该避免用各种随机的东西来填充你的PCH; macros,常量,# #defines和各种小型库。 一般来说,你应该省略大部分源文件中不需要的东西 。 把各种各样的东西放在你的PCH中,只是增加了一些权重和依赖。 我看到人们把所有他们连接的东西放在PCH中。 实际上,在大多数情况下,辅助框架通常只需要几个翻译就可以看到。 例如“这里是我们的StoreKit的东西 – 让我们只在必须可见的位置导入StoreKit,具体来说,这3个翻译”。 这可以减less构build时间,并帮助您跟踪自己的依赖关系,从而更轻松地重用代码。 所以在一个ObjC项目中,你通常会停在基金会。 如果有很多的用户界面,那么你可以考虑添加UIKit或AppKit到你的PCH。 这一切都假设你想优化生成时间。 包括(几乎)所有东西的大型PCH的问题之一是消除不必要的依赖性非常耗时。 一旦你的项目的依赖性增加,你的构build时间增加,你需要通过消除不必要的依赖来减less构build时间。 而且,任何经常变化的东西通常都应该放在PCH之外。 更改需要全面重build。 有一些选项可以共享PCH。 如果您使用PCH,确实旨在支持共享。

就我个人的PCH而言:几年前我绝大多数目标都停止使用它们。 通常没有足够的资格。 请记住,我编写C ++,ObjC,ObjC ++和C – 编译器会为您的目标中的每个lang发出一个。 所以启用它们通常会导致编译时间更慢,I / O更高。 最终,增加依赖并不是打击复杂项目依赖的好方法。 使用多种语言/方言,给定目标所需的依赖关系有很大的不同。 不,我不会build议每个项目都是最优的,但是这对大项目中的依赖pipe理有一定的帮助。


参考


笔记

  • 这个问题最初是在模块介绍前几年提出的。
  • 目前(Xcode 5.0),模块适用于C和ObjC,但不适用于C ++。

我同意bbum。 我对PCH文件的看法是它几乎只包含#include或者#import语句。 所以如果你有一堆有用的高级macros,按照Common.h#import那样定义它们,就像bbumbuild议的那样。

我通常会更进一步,使用PCH文件来XXCategories.h一个名为XXCategories.h的文件(其中XX是您使用的类命名前缀约定),其中包含所有我的UIKit和Foundation类类别的#import s: NSString+XXAdditions.hUIColor+XXAdditons.h

创build一个头文件“macros.h”

将此标题导入Prefix.pch

在这个macros.h中放置了所有的框架和其他重要的东西。

如果你担心性能,不要担心,看看苹果说:

头和性能

如果担心包含主头文件可能会导致程序膨胀,请不要担心。 由于OS X接口是使用框架实现的,因此这些接口的代码驻留在dynamic共享库中,而不是驻留在可执行文件中。 另外,只有程序使用的代码才会在运行时加载到内存中,因此您的内存占用空间同样很小。 至于在编译过程中包含大量的头文件,再次不要担心。 Xcode提供了一个预编译头文件来加快编译时间。 通过一次编译所有的框架头文件,除非添加新的框架,否则不需要重新编译头文件。 与此同时,您可以使用包含的框架中的任何接口,而不会影响性能。

也在我的macros。我把很多常量,如:

 // 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];