#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. Python练习题–持续更新

    1.你是一个高级测试工程师,现在要做性能测试,需要你写一个函数,批量生成一些注册使用的账号. 产生的账号是以@163.com结尾,长度由用户输入,产生多少条也由用户输入,用户名不能重复,用户名必须由大 ...

  2. Eclipse、IDEA安装JavaFX

    简介 JavaFX插件 e(fx)eclipse是一组工具和必要的库,它们帮助您执行JavaFX编程,确保您已经作为插件将其安装在eclipse上了. JavaFX Scene Builder Jav ...

  3. Hihocoder 1561 观光旅行(启发式合并+贪心)

    题目链接 Hihocoder 1561 首先对原图求$MST$ 我们发现某条边成为某两个点的关键路径的必要条件是这条边是最小生成树的树边. 所以我们求$MST$的同时进行启发式合并. 把$size$小 ...

  4. inux IO 内核参数调优 之 参数调节和场景分析

    http://backend.blog.163.com/blog/static/2022941262013112081215609/ http://blog.csdn.net/icycode/arti ...

  5. UVA - 11178-Morley’s Theorem

    就是给出一个等边三角形的三个顶点坐标 然后每一个角的三等分线会交错成一个三角形,求出这个三角形的顶点坐标 一開始.我题意理解错了--还以为是随意三角形,所以代码可以处理随意三角形的情况 我的做法: 通 ...

  6. Java并发编程(三)volatile域

    相关文章 Java并发编程(一)线程定义.状态和属性 Java并发编程(二)同步 Android多线程(一)线程池 Android多线程(二)AsyncTask源代码分析 前言 有时仅仅为了读写一个或 ...

  7. Gas Station,转化为求最大序列的解法,和更简单简单的Jump解法。——贪心、转化

    Gas Station There are N gas stations along a circular route, where the amount of gas at station i is ...

  8. goang Receiver & interface

    package main import ( "fmt" ) type Pointer struct { x string } func (this *Pointer) PrintX ...

  9. js 监控浏览器关闭(完美兼容chrome & ie & fire fox)

    var UnloadConfirm = {}; UnloadConfirm.MSG_UNLOAD = "数据尚未保存,离开后可能会导致数据丢失\n\n您确定要离开吗?"; Unlo ...

  10. Python基础二--基本控制语句

    基本接触每一种语言,都须要做的:1.print 一个"Hello world!" 2.了解主要的数据类型 3.学习控制语句. 当我们学习控制语句,一般都离不开if,for ,whi ...