2010-05-16 143 views
87

我见过许多开发人员将各种便利宏添加到其iOS项目的Prefix.pch中。iOS Prefix.pch最佳实践

你推荐添加到iOS Prefix.pch文件中的什么(或不)?你的Prefix.pch是什么样的?

+2

只需将您的宏放入头文件中,例如'Macros.h',然后将该文件导入到您的'prefix.pch'中。 – Malloc 2013-02-08 14:26:20

+0

关于这个问题的详细博客文章:http://www.cimgf.com/2010/05/02/my-current-prefix-pch-file/ – hpique 2010-06-25 16:30:57

+0

我也面临同样的问题...如何解决Xcode 6.1 – Singapore 2015-02-11 12:20:25

回答

121

Ewww ...不要把宏放在.pch文件中!根据定义,.pch文件是特定于项目的预编译头文件。它确实不应该超出该项目的范围,它实际上不应该包含任何内容,除了#include s和#import s。

如果你有一些宏等,你想报头之间的共享,然后把脚伸在自己的头文件 - Common.h或别的什么 - 并且#include在.PCH的开始。

+0

你会在Common.h中包含什么? – hpique 2010-05-17 09:34:52

+4

什么都没有;我只会把各种#defines等等放在里面。 – bbum 2010-05-19 22:40:19

8

我同意bbum。我对PCH文件的看法是它几乎只包含#include#import语句。因此,如果您有一堆有用的高级宏,请按照bbum的建议,将它们定义为Common.h#import文件。

我通常更进一步,并使用PCH文件#import一个名为XXCategories.h文件(其中XX是使用class命名前缀约定),其中包含#import是为我所有的UIKit和基金类属:NSString+XXAdditions.hUIColor+XXAdditons.h,等等。

+0

我只是好奇。在.PCH文件中,导入带有各种'#import'的Common.h和直接导入这些'#import'有什么区别?这些不一样吗?还是会影响性能? – Hlung 2012-04-04 09:57:56

+0

据我所知,没有*真正的*差异。我猜,这更像是一种最佳做法。而不是将一堆宏和其他东西放到你的PCH文件中,它应该只用于'#import'和'#include'。 – LucasTizma 2012-04-04 17:54:17

+1

区别在于可重用性。 PCH是项目特定的。 Common.h对于许多项目来说是很常见的。这就好比问你为什么不把所有的util类放到你的项目中,而不是创建一个你可以重用的子项目。虽然是一个人为的例子,因为它只是一个简单的复制粘贴...但复制粘贴是淘气。 – bandejapaisa 2013-06-20 10:34:08

35

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

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

使用模块,你不需要一个PCH,你可能应该完全废除它们 - 有利于使用@import本地依赖项。在这种情况下,PCH只会从中输入将内含物包含在依赖项中(您应该继续使用IMO)。

现在,如果我们回顾一下原来的问题:你应该避免用各种随机的东西来填充你的PCH;宏,常量,#defines,以及各种小型库。一般来说,您应该忽略大部分源文件确实没有必要。在PCH中放入各种各样的东西只是增加了一些权重和依赖。我看到人们把他们链接的所有东西放在PCH中。实际上,在大多数情况下,辅助框架通常只需要几个翻译就可以看到。例如。 “这里是我们的StoreKit的东西 - 让我们只在必须可见的地方导入StoreKit,具体来说,这3个翻译”。这可以减少构建时间,并帮助您跟踪自己的依赖关系,从而更轻松地重用代码。所以在一个ObjC项目中,你通常会停留在基金会。如果有很多用户界面,那么你可以考虑将UIKit或AppKit添加到你的PCH。这都假设你想优化构建时间。包括(几乎)所有内容的大型PCH的问题之一是消除不必要的依赖性非常耗时。一旦项目的依赖性增加并且构建时间增加,则需要通过消除不必要的依赖性来减少构建时间。而且,任何经常变化的东西通常都应该保存在PCH之外。更改需要完全重建。有一些选项可以共享PCH。如果您使用PCH,确实旨在支持共享。至于我在PCH中放置的东西:几年前我绝大多数目标都停止使用它们。通常没有足够的资格获得资格。请记住,我编写C++,ObjC,ObjC++和C--编译器为您的目标中的每个lang发出一个。所以启用它们通常会导致编译时间更慢和I/O更高。最终,增加依赖并不是打击复杂项目依赖的好方法。使用多种语言/方言时,给定目标所需的依赖关系存在很大差异。不,我不会建议,对于每个项目来说都是最优的,但是这确实给大型项目中的依赖管理带来了一些视角。


参考


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

对于启用模块的项目完成重建意味着什么。你知道这个新的-Swift.h桥头是绝对不适合.pch的。但我看到有人这样做。所以你可以看到是否有人这样做。我们在.pch中有一个总是变化的标题。因此,每次重新生成-Swift.h时,都会重新生成.pch文件中的所有内容。你同意吗?你有更多的投入? – MadNik 2016-12-03 08:54:16

+0

@MadNik假设您的应用程序的PCH包含您正在积极开发的库/框架的主标题。例如:'#import“MyLib/MyLib.h”'。只要'MyLib.h'包含的文件发生更改,应用程序中的每个源文件都必须重新编译。如果仅在一个源文件中使用MyLib,则只有在MyLib更改时必须重新编译该文件。相信与否,这些天我没有使用任何PCH文件。 – justin 2016-12-13 06:30:59

6

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

进口这头到Prefix.pch

在这种macros.h把所有的框架和其他重要的事情。

如果你担心性能,请不要着急,看看什么苹果说:

页眉和性能

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

也在我的宏。h我输入了许多常量,如:

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

另一个有用的地方:'#define async(...)dispatch_async(dispatch_get_main_queue(),__VA_ARGS__)'...在主线程上运行块:'async(^ {self.someLabel.text = @“:D” ;});' – 2016-03-30 15:42:02