#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 ;
} #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》;

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

  1. 预处理指令#pragma

    #pragma介绍 #pragma是一个预处理指令,pragma的中文意思是『编译指示』.它不是Objective-C中独有的东西(貌似在C/C++中使用比较多),最开始的设计初衷是为了保证代码在不同 ...

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

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

  3. Effective Objective-C 2.0 — 第四条:多用类型常量,少用#define预处理指令

    第四条:多用类型常量,少用#define预处理指令 使用#define 预处理的坏处:定义出来的常量没有类型信息,编译器只是会在编译前据此执行查找与替换操作.即使有人重新定义了常量值,编译器也不会产生 ...

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

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

  5. C#中的预处理指令

    C#中的预处理指令 作为预处理中的一对:#region name ,#endregion可能是大家使用得最多的,我也常用它来进行代码分块,在一个比较长的cs文件中,这么做确实是一件可以让你使代码更清晰 ...

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

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

  7. iOS预处理指令

    预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器.可见预处理过程先于编译器对源代码进行处理. 预处理指令是以#开头的代码行,#后是指令关键字,在关键字和#号之间允许存在任意个数的空 ...

  8. #pragma预处理指令讲解

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

  9. C# 预处理指令

    导读 1.什么是预处理 2.预处理的好处 3.C#中的常见预处理指令 4.总结 什么是预处理         在计算机科学中,预处理通常是指利用某一程序(通常是预处理器)对某一格式的源码(如.cs C ...

随机推荐

  1. AC日记——美元汇率 洛谷 P1988

    题目背景 此处省略maxint+1个数 题目描述 在以后的若干天里戴维将学习美元与德国马克的汇率.编写程序帮助戴维何时应买或卖马克或美元,使他从100美元开始,最后能获得最高可能的价值. 输入输出格式 ...

  2. Python种使用Excel

    今天用到Excel的相关操作,看了一些资料,借此为自己保存一些用法. 参考资料: python excel 的相关操作 python操作excel之xlrd python操作Excel读写--使用xl ...

  3. Vijos——1359 Superprime

    Superprime 描述 农民约翰的母牛总是生产出最好的肋骨.你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们. 农民约翰确定他卖给买方的是真正的质数肋骨,是因为从右边开始切下肋骨,每次还 ...

  4. 四则运算表达式树 C++模板 支持括号和未知数

    首先允许我吐槽CSDN的MARKDOWN,简直难用的不行. 程序的原理是将表达式分治转换为二叉树,再在二叉树上递归计算结果.如同以下表达式:x+5*y-(6/(1-5.5))可以表达为以下二叉树(抱歉 ...

  5. luogu P1886 滑动窗口(单调队列

    题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...

  6. Annotation基本概念,作用以及举例说明。

    Annotation即注解,是Jav5新特征,Annotatio提供一些本来不属于程序的数据,用来将任何的信息或元数据(metadata)与程序元素(类.方法.成员变量等)进行关联.为程序的元素(类. ...

  7. http://www.cnblogs.com/shihaiming/

    原文:http://www.bubuko.com/infodetail-917303.html 右击项目,点击Run as,如下图: 即可看到有很多现有的maven命令,点击即可运行,并在控制台可以看 ...

  8. 深入GCD(五):资源竞争

    概述我将分四步来带大家研究研究程序的并发计算.第一步是基本的串行程序,然后使用GCD把它并行计算化.如果你想顺着步骤来尝试这些程序的话,可以下载源码.注意,别运行imagegcd2.m,这是个反面教材 ...

  9. C++常用字符串分割方法

    一.用strtok函数进行字符串分割 原型: char *strtok(char *str, const char *delim); 功能:分解字符串为一组字符串. 参数说明:str为要分解的字符串, ...

  10. Golang Global Variable access

    golang 中全局变量的问题. ------------------------------------------------------------------ 17down votefavor ...