iOS开发之宏深度学习

来源:互联网 发布:乌镇人工智能报告 编辑:程序博客网 时间:2024/06/06 03:58

宏定义在C系开发中可以说占有举足轻重的作用。底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行。而在更高层级进行开发时,我们会将更多的重心放在业务逻辑上,似乎对宏的使用和依赖并不多。但是使用宏定义的好处是不言自明的,在节省工作量的同时,代码可读性大大增加。 如果想成为一个能写出漂亮优雅代码的开发者,宏定义绝对是必不可少的技能(虽然宏本身可能并不漂亮优雅XD)。但是因为宏定义对于很多人来说,并不像业务逻辑那样是每天会接触的东西。即使是能偶尔使用到一些宏,也更多的仅仅只停留在使用的层级,却并不会去探寻背后发生的事情。 有一些开发者确实也有探寻的动力和意愿,但却在点开一个定义之后发现还有宏定义中还有其他无数定义,再加上满屏幕都是不同于平时的代码,既看不懂又不变色,于是乎心生烦恼,怒而回退。本文希望通过循序渐进的方式,通过几个例子来表述C系语言宏定义世界中的一些基本规则和技巧,从0开始,希望最后能让大家至少能看懂和还原一些相对复杂的宏。考虑到我自己现在objc使用的比较多,这个站点的读者应该也大多是使用objc的,所以有部分例子是选自objc,但是本文的大部分内容将是C系语言通用。

入门 如果您完全不知道宏是什么的话,可以先来热个身。很多人在介绍宏的时候会说,宏嘛很简单,就是简单的查找替换嘛。嗯,只说对了的一半。C中的宏分为两类,对象宏(object-like macro)和函数宏(function-like macro)。对于对象宏来说确实相对简单,但却也不是那么简单的查找替换。

对象宏一般用来定义一些常数,#define关键字表明即将开始定义一个宏,紧接着的M_PI是宏的名字,空格之后的数字是内容。类似这样的#define X A的宏是比较简单的,在编译时编译器会在语义分析认定是宏后,将X替换为A,这个过程称为宏的展开。

函数宏顾名思义,就是行为类似函数,可以接受参数的宏。在定义的时候,如果我们在宏名字后面跟上一对括号的话,这个宏就变成了函数宏,相比对象宏来说,函数宏要复杂一些,但是看起来也相当简单。现在热身结束,让我们正式开启宏的大门。

宏的世界,小有乾坤 因为宏展开其实是编辑器的预处理,因此它可以在更高层级上控制程序源码本身和编译流程。而正是这个特点,赋予了宏很强大的功能和灵活度。但是凡事都有两面性,在获取灵活的背后,是以需要大量时间投入以对各种边界情况进行考虑来作为代价的。可能这么说并不是很能让人理解,但是大部分宏(特别是函数宏)背后都有一些自己的故事,挖掘这些故事和设计的思想会是一件很有意思的事情。另外,我一直相信在实践中学习才是真正掌握知识的唯一途径,虽然可能正在看这篇博文的您可能最初并不是打算亲自动手写一些宏,但是这我们不妨开始动手从实际的书写和犯错中进行学习和挖掘,因为只有肌肉记忆和大脑记忆协同起来,才能说达到掌握的水准。可以说,写宏和用宏的过程,一定是在在犯错中学习和深入思考的过程,我们接下来要做的,就是重现这一系列过程从而提高进步。

如果您常年做苹果开发,却没有见过或者完全不知道XCTAssertTrue是什么的话,强烈建议补习一下测试驱动开发的相关知识,我想应该会对您之后的道路很有帮助。如果你已经很熟悉这个命令了,那我们一起开始来看看幕后发生了什么。 有了上面的基础,相信您大体上应该可以自行解读这个宏了。({...})的语法和##都很熟悉了,这里有三个值得注意的地方,在这个宏的一开始,我们后面的的参数是format...,这其实也是可变参数的一种写法,和...与__VA_ARGS__配对类似,{NAME}...将于{NAME}配对使用。也就是说,在这里宏内容的format指代的其实就是定义的先对expression取了两次反?我不是科班出身,但是我还能依稀记得这在大学程序课上讲过,两次取反的操作可以确保结果是BOOL值,这在objc中还是比较重要的(关于objc中BOOL的讨论已经有很多,如果您还没能分清BOOL, bool和Boolean,可以参看NSHisper的这篇文章)。然后就是@#expression这个式子。我们接触过双井号##,而这里我们看到的操作符是单井号#,注意井号前面的@是objc的编译符号,不属于宏操作的对象。单个井号的作用是字符串化,简单来说就是将替换后在两头加上”“,转为一个C字符串。这里使用@然后紧跟#expression,出来后就是一个内容是expression的内容的NSString。然后这个NSString再作为参数传递给_XCTRegisterFailure和_XCTFailureDescription等,继续进行展开,这些是后话。简单一瞥,我们大概就可以想象宏帮助我们省了多少事儿了,如果各位看官要是写个断言还要来个十多行的话,想象都会疯掉的吧。 另外一个例子,找了人民群众喜闻乐见的ReactiveCocoa(RAC)中的一个宏定义。对于RAC不熟悉或者没听过的朋友,可以简单地看看Limboy的一系列相关博文(搜索ReactiveCocoa),介绍的很棒。如果觉得“哇哦这个好酷我很想学”的话,不妨可以跟随raywenderlich上这个系列的教程做一些实践,里面简单地用到了RAC,但是都已经包含了RAC的基本用法了。RAC中有几个很重要的宏,它们是保证RAC简洁好用的基本,可以说要是没有这几个宏的话,是不会有人喜欢RAC的。其中RACObserve就是其中一个,它通过KVC来为对象的某个属性创建一个信号返回(如果你看不懂这句话,不要担心,这对你理解这个宏的写法和展开没有任何影响)。对于这个宏,我决定不再像上面那样展开和讲解,我会在最后把相关的宏都贴出来,大家不妨拿它练练手,看看能不能将其展开到代码的状态,并且明白其中都发生了些什么。如果你遇到什么问题或者在展开过程中有所心得,欢迎在评论里留言分享和交流 :) 好了,这篇文章已经够长了。希望在看过以后您在看到宏的时候不再发怵,而是可以很开心地说这个我会这个我会这个我也会。最终目标当然是写出漂亮高效简洁的宏,这不论对于提高生产力还是震慑你的同事提升自己实力都会很有帮助。 另外,在这里一定要宣传一下关注了很久的@hangcom 吴航前辈的新书《iOS应用逆向工程》。很荣幸能够在发布之前得到前辈的允许拜读了整本书,可以说看的畅快淋漓。我之前并没有越狱开发的任何基础,也对相关领域知之甚少,在这样的前提下跟随书中的教程和例子进行探索的过程可以说是十分有趣。我也得以能够用不同的眼光和高度来审视这几年所从事的iOS开发行业,获益良多。可以说《iOS应用逆向工程》是我近期所愉快阅读到的很cool的一本好书。现在这本书还在预售中,但是距离1月28日的正式发售已经很近,有兴趣的同学可以前往亚马逊或者ChinaPub的相关页面预定,相信这本书将会是iOS技术人员非常棒的春节读物。 最后是我们说好的留给大家玩的练习,我加了一点注释帮助大家稍微理解每个宏是做什么的,在文章后面留了一块试验田,大家可以随便填写玩弄。总之,加油!


源博客:http://www.2cto.com/kf/201401/275057.html

0 0
原创粉丝点击