看了《禅与 Objective-C 编程艺术》,发现不少平时不注意的或注意但没有系统总结的东西,特此记录一下。

这次没有整理完,后续更新会结合手里的一些其他资料整理。

新博客wossoneri.com传送门

完整的介绍看这两个链接

Google开源项目风格指南

禅与 Objective-C 编程艺术 (Zen and the Art of the Objective-C Craftsmanship 中文翻译)

本文的意义就是找出一些我自己平时不注意的知识点进行总结,同时提出一些自己的观点,然后自己没事看看总结,提高编码质量。

条件语句

条件语句体应该总是被大括号包围。

我经常为了让代码看起来干净一些,所以对于条件语句体内只有一行代码的时候,我就会省去大括号以减少代码行数。

像这样:

  1. if (!error)
  2. return success;
  3. //or
  4. if (!error) return success;

这样写很容易带来隐患,比如增加一行代码时,就容易对这行代码是在语句体内还是外产生误解导致错误。注释一行代码容易使后面一行代码成为语句体内的内容。

所以老老实实把代码写规范了:

  1. if (!error) {
  2. return success;
  3. }

尤达表达式

星球大战中尤达大师的讲话方式,总是用倒装的语序

文章不建议使用尤达表达式,即不要使用常量和变量比较的方式。

比如:

  1. if (5 == count) { ...
  2. //or
  3. if ([@42 isEqual:myValue]) { ...

建议写成:

  1. if (count == 5) { ...
  2. //or
  3. if ([myValue isEqual:@42]) { ...

对于这一点,我有一些异议。因为对于第一种写法,写成5 == count可以避免把==写成=,如果按照不用尤达的写法,当我把比较写成赋值时count = 5,编译器是无法检测出我的失误的,而且对于这类失误,自己debug的时候也很难发现。而对于第二种写法使用isEqual方法就不存在这种问题。

所以这一点见仁见智吧。面对if (5 == count)这类条件语句,我还是偏向用尤达表达式的。

nil 和 BOOL 的检查

因为 nil 是 解释到 NO,所以没必要在条件语句里面把它和其他值比较。同时,不要直接把它和 YES 比较,因为 YES 的定义是 1, 而 BOOL 是 8 bit的,实际上是 char 类型。

这一点很重要,不要在条件语句内出现YES或者NO,多使用非运算符。

不推荐:

  1. if (someObject == YES) { ... // Wrong
  2. if (myRawValue == YES) { ... // Never do this.
  3. if ([someObject boolValue] == NO) { ...

推荐:

  1. if (someObject) { ...
  2. if (![someObject boolValue]) { ...
  3. if (!someObject) { ...

黄金大道

在使用条件语句编程时,代码的左边距应该是一条“黄金”或者“快乐”的大道。

也就是说,不要嵌套 if 语句。使用多个 return 可以避免增加循环的复杂度,并提高代码的可读性。

这一点我深有感触,在以往编码的时候,我都很耿直的把一些方法写到嵌套分支里。这样写的容易,但改代码逻辑的时候就麻烦了。

比如:

  1. - (void)someMethod {
  2. if ([someOther boolValue]) {
  3. //Do something important
  4. // blablabla ...
  5. }
  6. }

这种情况下,一个是代码看起来很复杂,另一个是改逻辑的时候,blablabla的内容都要拷贝出来,放在新修改的逻辑中去。

所以直到有一次思考优化代码的时候,我才想起来用相反的逻辑去处理它,即使用 return。比如:

  1. - (void)someMethod {
  2. if (![someOther boolValue]) {
  3. return;
  4. }
  5. //Do something important
  6. }

把逻辑判断单独择出来,处理代码就直接放在函数里。不符合逻辑的 return 掉,符合逻辑的直接就会运行到处理代码处。而且这样写代码层次很清晰。

Case 语句

除非编译器强制要求,括号在 case 语句里面是不必要的。但是当一个 case 包含了多行语句的时候,需要加上括号。

个人经验,好像在 case 中创建实例的时候,编译器会提醒你要为这个 case 加上括号。

  1. switch (condition) {
  2. case 1:
  3. // ...
  4. break;
  5. case 2: {
  6. // ...
  7. // Multi-line example using braces
  8. break;
  9. }
  10. case 3:
  11. // ...
  12. break;
  13. default:
  14. // ...
  15. break;
  16. }

常量使用、枚举和命名规范

见这篇博客:Objective-C 常量和枚举

方法

方法名与方法类型 (-/+ 符号)之间应该以空格间隔。方法段之间也应该以空格间隔(以符合 Apple 风格)。参数前应该总是有一个描述性的关键词。

这里要注意的一点是尽量少用 and 这个词。我因为入门的时候看的书经常用 and ,感觉这样阅读起来比较连贯,所以也养成了写 and 的习惯。后来感觉加 and 的确不是很好。关于看书命名这一块推荐看一下 Swift 的函数命名,因为 Swift 设计的时候一部分考虑到了 OC 当前的设计思想,同时对旧设计思想有了一些优化。看完你就会有自己的一套理解了。

不推荐写法:

  1. - (void)setT:(NSString *)text i:(UIImage *)image;
  2. - (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;
  3. - (id)taggedView:(NSInteger)tag;
  4. - (instancetype)initWithWidth:(CGFloat)width andHeight:(CGFloat)height;
  5. - (instancetype)initWith:(int)width and:(int)height; // Never do this.

推荐写法:

  1. - (void)setExampleText:(NSString *)text image:(UIImage *)image;
  2. - (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells:(BOOL)flag;
  3. - (id)viewWithTag:(NSInteger)tag;
  4. - (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;

美化代码

空格

  • 缩进使用 4 个空格。 永远不要使用 tab。可以在 Xcode 中设置按 tab 插入 4 个空格。
  • 方法的大括号和其他的大括号(if/else/switch/while 等) 总是在同一行开始,在新起一行结束。

第一点就不说了,前段时间看文章说还有人用 3 个空格,8 个空格的。个人还是觉得 4 空格比较舒服。

第二点是要注意的,可能以前看的初级书都是这样写:

  1. if (user.isHappy)
  2. {
  3. //Do something
  4. } else {
  5. //Do something else
  6. }

但分开写的话代码层次关系会更明显:

  1. if (user.isHappy) {
  2. //Do something
  3. }
  4. else {
  5. //Do something else
  6. }
  • 方法之间应该要有一个空行来帮助代码看起来清晰且有组织。 方法内的空格应该用来分离功能,但是通常不同的功能应该用新的方法来定义。
  • 优先使用 auto-synthesis。但是如果必要的话, @synthesize and @dynamic
  • 在实现文件中的声明应该新起一行。
  • 应该总是让冒号对齐。有一些方法签名可能超过三个冒号,用冒号对齐可以让代码更具有可读性。即使有代码块存在,也应该用冒号对齐方法。

这几点 Xcode 会帮你做一部分,比如说冒号对齐在 Xcode 里就是自动的。但还是注意一下吧。

不推荐:

  1. [UIView animateWithDuration:1.0 animations:^{
  2. // something
  3. } completion:^(BOOL finished) {
  4. // something
  5. }];

推荐:

  1. [UIView animateWithDuration:1.0
  2. animations:^{
  3. // something
  4. }
  5. completion:^(BOOL finished) {
  6. // something
  7. }];

换行

之前看过一个建议,就是一行代码保持在 80 个字符。

后来在不同的 IDE 下编码,发现不同的 IDE 在这一点上是一致的,就是可以设置一个字符长度的标志线,来提示代码长度。默认长度都是在 80 个字符。这个 Xcode 好像是默认不开启的,可以设置一下让那条线显示出来。

举例:

  1. self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];

一个像上面的长行的代码在第二行以一个间隔(2个空格)延续

  1. self.productsRequest = [[SKProductsRequest alloc]
  2. initWithProductIdentifiers:productIdentifiers];

括号

在以下的地方使用 Egyptian风格 括号 (译者注:又称 K&R 风格,代码段括号的开始位于一行的末尾,而不是另外起一行的风格。关于为什么叫做 Egyptian Brackets,可以参考 http://blog.codinghorror.com/new-programming-jargon/ )

  • 控制语句 (if-else, for, switch)

非 Egyptian 括号可以用在:

  • 类的实现(如果存在)
  • 方法的实现

看完就不要纠结 Java 风格 or C++ 风格了...

未完...

很多内容在整理...

[Objective-C]编程艺术 笔记整理的更多相关文章

  1. JavaScript DOM编程艺术 笔记(一)

    探测浏览器品牌版本代码-----浏览器嗅探 代码 JavaScript==ECMAScript java几乎可以部署在任何环境,js只应用于web浏览器 API是一组得到各方面共同认同的基本约定(元素 ...

  2. oracle sql 高级编程 历史笔记整理

    20130909 周一 oracle sql 开发指南 第7章 高级查询 1.层次化查询select level,ttt.*,sys_connect_by_path(ttt.col1,',') fro ...

  3. javascript dom编程艺术笔记之图片库的改进

    dom的操作要遵守的原则 1.平稳退化 2.分离javascript 3.向后兼容 4.性能考虑 改进后的显示图片方法 function showpic(whichpic){ if(!document ...

  4. javascript dom 编程艺术笔记 第四章:图片库

    首先先建立一个html文件,建立一个图片库 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &q ...

  5. javascript dom编程艺术笔记第三章:DOM操作的5个基本方法

    JavaScript的 DOM操作,主要是对DOM这三个字母中D.O.M的操作.D代表的是document(文档),即我们可以使用javascript对文档进行操作,O代表的是object(对象),对 ...

  6. dom编程艺术笔记2--第三章

    DOM 1.dom:简单理解为文档对象模型<==>节点树 2.宿主对象:浏览器提供的对象—>document对象 3. html标签为树顶点元素 head body为html子元素以 ...

  7. dom编程艺术笔记1--第二章

    第二章语法部分: 1.js注释:<!-- XXXXX 而“-->”这部分js会认为是注释内容的一部分 2.var 声明变量 不用声明变量类型 3.声明使用一个数组语法:var object ...

  8. JavascriptDom编程艺术(笔记)

    如果想快速学习dom的话,建议去菜鸟教程,比较浅显易懂,实战性较强.我是看纸质的书,主要是花钱,心疼,所以看完,容易记住. 1.重点: .变量 -.var修饰 -.赋值,用=号,例如ver age = ...

  9. JavaScript DOM编程艺术 笔记(四)

    DOM document   object model(map) 家谱树---节点树 父 子  兄弟 元素节点  <div> 文本节点  内容 属性节点   value  src getE ...

随机推荐

  1. [Leetcode]895.最大频率栈

    Problem 实现 FreqStack,模拟类似栈的数据结构的操作的一个类. FreqStack 有两个函数: push(int x),将整数 x 推入栈中. pop(),它移除并返回栈中出现最频繁 ...

  2. [学习笔记]修改关键跳无效且关键CALL又不存在的情况

    先用DI查下壳,VC++写的,无壳. 然后,打开软件看一下软件注册的情况 有弹窗,那载入OD看看能不能搜索到字符串 回到反汇编窗口,发现有两个JE都跳过了注册成功的代码 似乎很简单的样子,只要NOP掉 ...

  3. mac Navicat 破解+汉化(亲测可用)

    Navicat Premium 12 的版本 破解太麻烦,最后选择 Navicat Premium 11.0.16 下载:地址 提取码:h3rq ps:用的是功能,不是版本 为了一次就成功,请先执行下 ...

  4. 【shiro】(1)---了解权限管理

    了解权限管理 一.概念 1.什么是权限管理 只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源. 权限管理包 ...

  5. sql server 索引阐述系列四 表的B-Tree组织

    一.概述 说到B-tree组织,就是指索引,它可以提供了对数据的快速访问.索引使数据以一种特定的方式组织起来,使查询操作具有最佳性能.当数据表量变得越来越大,索引就变得十分明显,可以利用索引查找快速满 ...

  6. spark最新源码下载并导入到开发环境下助推高质量代码(Scala IDEA for Eclipse和IntelliJ IDEA皆适用)(以spark2.2.0源码包为例)(图文详解)

    不多说,直接上干货! 前言   其实啊,无论你是初学者还是具备了有一定spark编程经验,都需要对spark源码足够重视起来. 本人,肺腑之己见,想要成为大数据的大牛和顶尖专家,多结合源码和操练编程. ...

  7. clion调试postgresql

    clion怎么调试postgresql呢? clion使用cmake去编译项目的,但是大家编译postgresql用的是make.虽然项目中也有CMakeLists.txt文件,但是cmake会报错, ...

  8. Perl语法的基本规则

    因为是比较凌乱的用法规则收集,所以能看懂则看,不能看懂也无所谓.以后也会遇到. Perl脚本第一行使用#!.Perl的后缀名一般为".plx"或".pl",运行 ...

  9. Spring Cloud Config采用Git存储时两种常用的配置策略

    由于Spring Cloud Config默认采用了Git存储,相信很多团队在使用Spring Cloud的配置中心时也会采用这样的策略.即便大家都使用了Git存储,可能还有各种不同的配置方式,本文就 ...

  10. Vue父组件传递异步获取的数据给子组件

    问题场景: 当父组件传给子组件的数据是在父组件中异步获取的时候,如何让子组件获取期望的值? 在父组件中: 首先在data()中定义data_detail为空: data(){ data_detail: ...