《禅与 Objective-C 编程艺术》读书笔记

Part1

任何在未来可复用的设计,无形当中可以提高代码质量,这也应该一直是程序员的追求。是否这样设计代码,就是大师和菜鸟的区别。

面向对面思想的深入理解、设计模式的灵活运用,我相信是通往大师之路必要的技能!


OC常用的设计模式:

  • 单例模式(Singleton)
  • 工厂模式(Factory)
  • 委托模式(Delegate)
  • 观察者模式(Observer)
  • NSNotification
  • KVO(Key Value Observing)
  • MVC

抽象工厂eg:
适用于iPhone与iPad的VC,不需要关心实现的细节,很nice的思想

@implementation ZOCKintsugiPhotoViewController

- (id)initWithPhotos:(NSArray *)photos
{
    if ([self isMemberOfClass:ZOCKintsugiPhotoViewController.class]) {
        self = nil;

        if ([UIDevice isPad]) {
            self = [[ZOCKintsugiPhotoViewController_iPad alloc] initWithPhotos:photos];
        }
        else {
            self = [[ZOCKintsugiPhotoViewController_iPhone alloc] initWithPhotos:photos];
        }
        return self;
    }
    return [super initWithNibName:nil bundle:nil];
}
// self = nil的目的是移除ZOCKintsugiPhotoViewController实例上的所有引用,实例(抽象类的实例)本身将会解除分配

初始化方法的设计

Part2

code organization is a matter of hygiene (代码组织是卫生问题)

三元运算符

当三元运算符的第二个参数(if 分支)返回和条件语句中已经检查的对象一样的对象的时候,下面的表达方式更灵巧:

推荐:

result = object ? : [self createObject];

不推荐:

result = object ? object : [self createObject];

Constants 常量

常量应该以驼峰法命名,并以相关类名作为前缀。
这里以SDWebImage举例:

  • 局部常量以k打头,eg:
  • 全局常量(建议通知名用全局常量)eg:
《禅与 Objective-C 编程艺术》读书笔记_第1张图片
《禅与 Objective-C 编程艺术》读书笔记_第2张图片

当你定义你自己的 NSNotification 的时候你应该把你的通知的名字定义为一个字符串常量,就像你暴露给其他类的其他字符串常量一样。你应该在公开的接口文件中将其声明为 extern 的, 并且在对应的实现文件里面定义。

因为你在头文件中暴露了符号,所以你应该按照统一的命名空间前缀法则,用类名前缀作为这个通知名字的前缀。

同时,用一个 Did/Will 这样的动词以及用 "Notifications" 后缀来命名这个通知也是一个好的实践。


Case语句

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

switch (condition) {
    case 1:
        // ...
        break;
    case 2: {
        // ...
        // Multi-line example using braces
        break;
       }
    case 3:
        // ...
        break;
    default: 
        // ...
        break;
}

当在 switch 语句里面使用一个可枚举的变量的时候,default 是不必要的。比如:

switch (menuType) {
    case ZOCEnumNone:
        // ...
        break;
    case ZOCEnumValue1:
        // ...
        break;
    case ZOCEnumValue2:
        // ...
        break;
}

此外,为了避免使用默认的 case,如果新的值加入到 enum,程序员会马上收到一个 warning 通知

当使用 enum 的时候,建议使用新的固定的基础类型定义,因它有更强大的的类型检查和代码补全。 SDK 现在有一个 宏来鼓励和促进使用固定类型定义 - NS_ENUM()

例子:

typedef NS_ENUM(NSUInteger, ZOCMachineState) {
    ZOCMachineStateNone,
    ZOCMachineStateIdle,
    ZOCMachineStateRunning,
    ZOCMachineStatePaused
};

参数断言

你的方法可能要求一些参数来满足特定的条件(比如不能为nil),在这种情况下啊最好使用 NSParameterAssert() 来断言条件是否成立或是抛出一个异常。
eg:

《禅与 Objective-C 编程艺术》读书笔记_第3张图片

相等性

确认我们要比较的是指针还是比较的是对象里真正的值
eg:


利用代码块

一个 GCC 非常模糊的特性,以及 Clang 也有的特性是,代码块如果在闭合的圆括号内的话,会返回最后语句的值

NSURL *url = ({
    NSString *urlString = [NSString stringWithFormat:@"%@/%@", baseURLString, endpoint];
    [NSURL URLWithString:urlString];
});

这个特性非常适合组织小块的代码,通常是设置一个类。他给了读者一个重要的入口并且减少相关干扰,能让读者聚焦于关键的变量和函数中。此外,这个方法有一个优点,所有的变量都在代码块中,也就是只在代码块的区域中有效,这意味着可以减少对其他作用域的命名污染。


last

永远不要在 init 方法(以及其他初始化方法)里面用 getter 和 setter 方法
详情看这里http://www.cnblogs.com/wsnb/p/6163377.html


希望会给大家带来帮助(o)/~

你可能感兴趣的:(《禅与 Objective-C 编程艺术》读书笔记)