#pragma介绍

#pragma是一个预处理指令,pragma的中文意思是『编译指示』。它不是Objective-C中独有的东西(貌似在C/C++中使用比较多),最开始的设计初衷是为了保证代码在不同编译器之间的兼容性,但随着时间推移,它出现在了更多更丰富的应用场景中。

#pragma代码是在编译期间处理的;它既不属于注释,也不属于逻辑代码的一部分;并且它和其他预处理命令譬如#ifdef ... #endif不同,它不会影响代码在运行时的逻辑处理,所以#pragma指令丝毫不会影响到程序在运行时的性能。根据Mattt Thompson大神的描述,在当前Xcode开发环境中,#pragma主要有两个应用场景:组织代码和屏蔽编译警告。

#pragma mark组织代码

组织代码是个人卫生问题,个人卫生不好(代码组织不好)不能反映人品(技术能力),但它在某种程度中影响了别人是否愿意和他搞基(合作)。在一个项目(尤其是多人合作的项目)中,应该有一个比较好的内部一致性编码习惯,不好的习惯或者缺乏一致性,会使得项目难以维持,协作也不便(这点笔者深有体会,笔者目前的项目有一个同事,编码能力尚可,但编码习惯实在太糟糕,代码紧凑,从来不空格,更妄谈空行和注释了,甚至经常不对齐,看他的代码,一点修改的欲望都没有,想的只是自己重写一遍=_=)。

在组织代码时充分使用#pragma mark就是写出『干净代码』的一个重要环节,就像这样:

#pragma mark - UIViewController
 
- (void)viewDidLoad {
 
[super viewDidLoad];
}
 
- (void)dealloc {
 
}
 
#pragma mark - IBAction
 
- (IBAction)loginNow:(id)sender {
 
}
 
#pragma mark - UITableViewDataSource
 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 0;
}
 
#pragma mark - UITableViewDelegate
 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 
}

上述代码中使用#pragma mark将@implementation中的代码(方法)分成了几个逻辑section,这种处理并没有改变程序逻辑,但我们在使用Xcode代码导航工具时可以在视觉上汲取片刻的欢愉:

组织N个方法为一个section的依据是什么呢?这个就见仁见智了。一般来说:

  • 将一个protocol的方法组织成一个section;
  • 将target-action类型方法组织成一个section;
  • 将notification相关方法组织成一个section;
  • 将需要override的父类方法组成成一个section;

#pragma屏蔽编译警告

使用#pragma mark来组织代码使用比较普遍,相对而言,使用#pragma指令屏蔽编译器和静态分析器的警告相对来说就比较新鲜了。

You know what is even more annoying than poorly-formatted code? Code that generates warnings. 编译警告很可恶,应该尽可能修改代码干掉这些警告,但是有些时候有些警告无法避免,譬如我们在编写@selector(aMethodName)这样的代码时,如果aMethodName没有在上下文中出现,可能会出现含有『undeclared-selector』关键词的warning,有洁癖的程序员会想到干掉这个warning,此时#pragma指令就派上用场了。譬如:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
if ([self.selectedViewController respondsToSelector:@selector(isReadyForEditing)]) {
boolNumber = [self.selectedViewController performSelector:@selector(isReadyForEditing)];
}
#pragma clang diagnostic pop

这是Clang编译器提供的一种解决方案,通过使用#pragma clang diagnostic push/pop来告诉编译器仅仅为某一特定部分代码(记得要在代码片段末尾使用pop将最初的diagnostic设置恢复哦)忽视特定警告。

上述示例中#pragma clang diagnostic ignored后面的"-Wundeclared-selector"指示的是『特定警告』,再别的应用场景中肿么知道该填写什么呢?网络是强大的,有一个(可能是N个)愤怒的网友对clang警告消息做了一个总结,之所以说这个网友“愤怒”,是因为其链接非常有意思:http://fuckingclangwarnings.com/

Finally, you can read more about the LLVM’s use of #pragma in the Clang Compiler User’s Manual.

最后,感谢大神Mattt Thompson,本文的参考资料完全来自于《#pragma》,本来想用自己的语言完成这篇博客,边读边写,最后发现几乎差不多了,没留下啥自己的东西,就这样吧!

参考资料

  1. #pragma》;
  2. clang diagnostics》;

预处理指令#pragma的更多相关文章

  1. C++ 预处理指令 #pragma

    http://www.cnblogs.com/qinfengxiaoyue/archive/2012/06/05/2535524.html

  2. #pragma预处理指令讲解

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

  3. 预处理指令中#Pragma

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

  4. #pragma 预处理指令详解

    源地址:http://blog.csdn.net/jx_kingwei/article/details/367312 #pragma  预处理指令详解              在所有的预处理指令中, ...

  5. C++中的#pragma 预处理指令详解

    源地址:http://blog.csdn.net/roger_77/article/details/660311 在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的状态 ...

  6. pragma comment的使用 pragma预处理指令详解

    pragma comment的使用 pragma预处理指令详解   #pragma comment( comment-type [,"commentstring"] ) 该宏放置一 ...

  7. C/C++预处理指令#define,#ifdef,#ifndef,#endif…

    2016年12月29日更新: 今天查看以前文件的时候, 突然发现了#error 这个预处理指令.然后回想一下工作, 发现这个指令使用场景还是很多的.比如: 一个项目的模块儿之多,源文件之大,代码之多, ...

  8. VC中预处理指令与宏定义详解

    刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个 ...

  9. C#学习笔记(十五):预处理指令

    C#和C/C++一样,也支持预处理指令,下面我们来看看C#中的预处理指令. #region 代码折叠功能,配合#endregion使用,如下: 点击后如下: 条件预处理 条件预处理可以根据给出的条件决 ...

随机推荐

  1. 7、二种 为二个不同的子网配置DHCP服务器(中继代理服务器)

    环境如下:        (参考之前,保证二个子网可以互相ping通) 虚拟机vm1        192.168.170.3                    VMnet8 (NAT模式) 虚拟 ...

  2. 2016 daily

    2016.01.06 leetcode 切题数达到 200+,截止目前 137.虽然一年 63 题看似不多,但是 easy 的题目基本已经切完,质量 >> 数量(专注 leetcode,可 ...

  3. Activity去Title的几种方式

    第一种:直接加一行代码: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInst ...

  4. Android系统中应用的安装和卸载的监听

    一.创建一个类继承BroadcastReceiver并且复写onReceive的方法 public class AppStateReceiver extends BroadcastReceiver { ...

  5. mybatis返回数据类型为map,值为null的key没返回

    创建mybatis-config.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...

  6. java-正则表达式过滤标签

    String str="one <a href=u.php?action=show&uid=122113 target=_blank>超链接文本</a> tw ...

  7. 关于List的ConcurrentModificationException

    对ArrayList的操作我们可以通过索引象来访问,也可以通过Iterator来访问,只要不对ArrayList结构上进行修改都不会造成ConcurrentModificationException, ...

  8. NSRunLoop

    1.什么是RunLoop 运行循环 一个线程对应一个RunLoop,主线程的RunLoop默认已经启动,子线程的RunLoop得手动启动(调用run方法) RunLoop只能选择一个Mode启动,如果 ...

  9. 【BZOJ-3998】弦论 后缀自动机

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2018  Solved: 662[Submit][Status] ...

  10. ReactNative 使用微软的CodePush进行热更新,继续填坑

    1.别被开发环境骗了 在我们开发react native的时候,一键运行工程,js改了,只要cmd+R就可以刷新了.然后会轻易以为真正app上线的时候也是一样,只要app一打开就是最新的. 其实!这是 ...