Effective Objective-C 2.0读书笔记

    2014-03-23 00:00     4 条评论

Effective Objective-C 2.0

1. 熟悉objective-c语言的内涵。

2. 尽量在头文件(.h)中引入其它头文件。

## 3. 尽量使用简化的语法,而不是使用等价方法(equivalent methods)

  1. 使用简化语法创建string,number,array,dictionary;因为这样比起使用正常的对象创建方法而言,更加简洁和有效。
  2. 使用数组下标或者字典key值访问容器元素
  3. 使用简化语法试图在数组或者字典中插入nil会有异常抛出的情况。因此,请总是确保你带插入的值不为nil

4. 尽量使用类型常量,而不是使用#define预编译指令

在定义一个常量的时候,尽量使用类型常量(eg. static const int kTagName 983);而不是使用#define 预编译指令。
实际上,当将变量定义为static const的时候,编译器并不会真正创建一个变量,而是像预编译指令一样使用字符串替代出现的变量定义,但是,这样使用的好处是类型是指定的。
eg:

extern NSString *const kLoginMgrNotification ;

const NSTimeInterval kAnimationDuration = 0.3 ;

请谨记以下要点:

  1. 避免使用宏定义。因为它不包含任何类型信息并且仅仅在编译之前查找并替换字符串。他们可以被重定义时没有警告,在应用程序的生命周期内不能保持一致性。
  2. 在实现文件中定义转换单元专用的常量,作为静态的常些量。这些常量不会在全局符号表中被暴露,被他字们加上命名空间。
  3. 在头文件中使用external关键字定义全局变量,并在相应的实现文件中给其赋值。这样,这些变量就会在全的名不
    需要局符号表中出现。

5.定义状态,选择,状态码的时候使用枚举类型

请谨记以下要点:

  1. 使用枚举类型来表示状态的状态机,方法中传递的选项,或者错误状态码,以便于使用可读的名称来代替不易理解的值。
  2. 枚举类型中的元素使用位运算"或""来表示需要多个值类型。
  3. Do not implement a default case in switch statements that handle enumerated types. This helps if you add to the enumeration, because the compiler will warn that the switch does not handle all the values.
  4. 使用 NS_ENUMNS_OPTIONS宏来定义枚举类型,而不是使用单一的类型定义枚举。这么做的目的是保证枚举类型的定义是一个可选择的定义,而不是由编译器决定枚举类型的定义 (使用c++类型或者c类型的枚举定义)

    比如:

    typedef NS_ENUM(NSUInteger, EOCConnectionState) {
        EOCConnectionStateDisconnected,
        EOCConnectionStateConnecting,
        EOCConnectionStateConnected,
    };
    typedef NS_OPTIONS(NSUInteger, EOCPermittedDirection) {
        EOCPermittedDirectionUp = 1 << 0,
        EOCPermittedDirectionDown = 1 << 1,
        EOCPermittedDirectionLeft = 1 << 2,
        EOCPermittedDirectionRight = 1 << 3,
    };
    

两个宏的定义如下:

 #if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) ||
     __has_feature(objc_fixed_enum))
     ) ||
     (!__cplusplus && __has_feature(objc_fixed_enum))
     #define NS_ENUM(_type, _name)
     enum _name : _type _name; enum _name : _type
     #if (__cplusplus)
     #define NS_OPTIONS(_type, _name)
     _type _name; enum : _type
     #else
     #define NS_OPTIONS(_type, _name)
     enum _name : _type _name; enum _name : _type
     #endif
#else
     #define NS_ENUM(_type, _name) _type _name; enum
     #define NS_OPTIONS(_type, _name) _type _name; enum
#endif

6. 理解属性(properties)

ABI(Application Binary interface):应用程序二进制接口。

In computer software,an application binary interface(ABI) is the interface between two programe modules ,one of which is ofter a library or operating system,at the level of machine code.An ABI determines such details as how functions are called and in which binary format information should be passed from one program component to next ,or to the operating system in the case of system call.

7. 在类内部访问实例变量时,直接进行访问,而不是通过getter方法进行访问

请谨记以下要点:

  1. 在类内部读取属性(property)值的时候,直接访问实例变量(而不是使用get方法)
  2. 在初始化方法(init)和dealloc方法中,无论是读取还是设置属性值,总是使用实例变量
  3. 有的时候,你读取属性的时候需要使用懒加载(lazily initialied),

比如:

- (NSObject *) objXXX{
    if(!_objXXX){
        _objXXX = [NSObject new];
    }
    return objXXX;
}

8. 理解对象的对等(equality)

请谨记以下要点:

  1. 假如你想要检查对象是否对等,你需要在你的对象中提供isEqual:和hash方法
  2. 对待的2个对象必须拥有相等的hash值,但是hash值相对的对象不一定对等
  3. 确定什么是必要的,以测试是否相等,而不是直截了当地检测每一个属性。
  4. Write hash methods that will be quick but provide a reasonably low level of collisions

9. 使用类簇模式隐藏实现细节

10. 使用关联对象为已有类附加用户数据

objc_setAssociatedObject方法的使用

请谨记以下要点:

  1. 关联提供一种将2个对象关联在一起的方法
  2. The memory-management semantics of associated objects can be defined to mimic owning or nonowning relationships
  3. 关联对象必须仅仅在一个不能修改的类中,因为使用对象关联很容易引入难于定位的bug

11. 理解objc_msgSend

类实现 -> 父类实现 -> 消息转发(message forwarding)

请谨记以下要点:

  1. 一个消息由:接受者,选择器selector,参数组成。执行一个消息是一个同步调用对象中的方法
  2. 当消息执行的时候,所有的消息通过动态消息分发系统来查找方法,并且执行方法

12. 理解消息转发(message forwarding)

动态方法解析(property中使用@dynamic关键字):

+ (BOOL)resolveInstanceMethod:(SEL)selector

代替消息接受者(replacement receiver):

- (id)forwardingTargetForSelector:(SEL)selector

完全转发机制(full forwarding mechanism):

- (id)forwardingTargetForSelector:(SEL)selector

消息转发机制:

请谨记以下要点:

  1. 消息转发机制仅仅是在一个对象对指定选择器(selector)不响应时的处理过程。
  2. 动态方法解析被用于在运行时,当方法被使用时,向已有类中添加方法
  3. 对象可以定义一个该对象不理解的对象,并使用该不理解的对象处理选择器
  4. full forwarding只有在之前的步骤都对指定的selector不处理的情况下,才会被执行

13. 考虑方法交叉(Method swizzling),以调试不透明的方法

在运行时,使用method_exchangeImplementations方法替换已有方法的实现;使用method_setImplementation方法设置已有方法的实现。

请谨记以下要点:

  1. 给定类的selector的方法实现,可以在运行时被新增/替换
  2. 方法交叉用于处理将一个方法切换为另一个方法,常用于添加新的特性到已有的方法实现中
  3. 仅用于调试通过运行时使用的方法干预通常是好的,但是不应该在实际项目中使用。

14.理解类对象是什么(understand what a class object is)

15. 使用前缀以避免名字冲突

16. 指定一个初始化方法(designated initializer)

请谨记以下要点:

  1. 在你的类中实现指定的初始化方法,并且用文档指出该初始化方法。所有的其它初始化方法都调用这个初始化方法。(避免以后修改初始化方法的时候,做多处修改)
  2. 假如指定的初始化方法和父类的初始化方法不同,保证指定的初始化方法被重写
  3. 在子类中重写父类的指定初始化方法,将子类不能被使用的指定初始化方法抛出异常

17. 实现描述方法(decription method)

请谨记以下要点:

  1. 实现description方法,为对象实例提供一个有意义的字符串描述
  2. 假如需要在调试时候

18. 尽量使用不可变对象(prefer immutable objects)

请谨记以下要点:

  1. 在可能的情况下,尽量创建不可变对象
  2. 在类catagroy方法中,重写read-only属性为read-write,以便于内部设值
  3. 提供共有方法改变类中的可变属性,而不是将一个可变提供给外部使用

19. 使用清晰和一致的名称

20. 为私有方法添加私有前缀(比如p_方法名)

请谨记以下要点:

  1. 为私有方法添加前缀,这样就可以很轻易的和共有方法进行区分
  2. 避免在方法前缀中使用下划线,因为这是苹果的保留用法

21. 理解Objective-C的错误模型

22. 理解NSCoping 协议

23 使用delegate和datasource协议用于对象间的交流

24. 使用categories用于分散类的实现,以便于类的关联

25. 为第三方类添加category方法时,添加方法前缀

26. 在category中,避免使用属性(property)

27. 使用匿名category用于隐藏类的实现细节

28. 使用协议提供匿名对象

29. 理解引用计数

30. 使用ARC让引用计数更易管理

31. 只在dealloc方法中释放引用和清除观察状态

32. 谨记内存管理时使用带异常(Exception)的安全代码

请谨记以下要点:

  1. 当异常被捕获时,请一定注意保证对try语句块中创建的对象,需要进行相应的清理
  2. 默认情况下,当出现异常时,ARC不会进行相应的清理处理。假如需要ARC进行相应的清理处理,可以使用**-fobjc-arc-exceptions **编译器指令,但是这样会生成大量的代码并且增加运行时的开销。

33.使用弱引用避免循环引用问题

34. 使用自动释放池块减少高内存占用(high-memory waterline)

35.使用僵尸变量帮助你调试内存问题

36. 避免使用retainCount

37. 理解blocks

38. 为常见blocsk类型创建 typedefs

39.使用处理块(handler blocks)来减少代码的隔离

40. 避免在blocks引用中引入循环引用问题

41. 线程同步优先使用分发队列(dispatch queue)而不是锁(locks)

42. 优先使用GCD代替performSelector系列方法

请谨记以下要点:

  1. performSelector系列方法在内存管理上存在潜在的危险,如果它没有办法确定哪些selector将被执行时, ARC编译器无法插入适当的内存管理调用。
  2. performSelector系列方法在方法参数数量,和返回值类型上非常有限
  3. performSelector系列方法在不同线程中执行一个selector时,使用GCD调用更加的好

43. 理解何时使用GCD,何时使用Operation queues

需要说明的第一点不同是,GCD是纯净的C api,然而Operation Queues 是objective-C对象。在GCD中,在队列中执行的任务是一个block,block是一个轻量级的数据结构。在另一方面Operation Queues确实objective-c对象,相比而言,更加重量级

使用NSOperation和NSOperationQueue的优点:

  1. 取消操作(cancelling operataions).
  2. 操作依赖(operation dependencies).
  3. 操作(operations)属性的Key-value observing
  4. 操作的优先级.在一个队列中,可以指定不同任务的优先级
  5. 可重用操作(reuse of operations)

请谨记以下要点:

  1. GCD不是多线程和任务管理的唯一解决方案
  2. operation queues 提供一个,高级别的Objective-C api,它可以做到大多数普通CGD可做的事情。这些队列也可以做更复杂的事情,可能会需要使用额外的GCD代码

44. 使用dispatch groups为了提供平台扩展优势

the original English description is :
Use dispatch groups to take advantage of platform scaling

此处的platform scaling指的是,假如CPU等资源丰富,比如针对单核,双核和多核cpu,同一的代码在多核,双核上的执行效率可以得到显著提高。

45. 使用dispatch_once已达到线程安全,单次代码执行的目的

46. 避免使用dispatch_get_current_queue

dispatch_get_current_queue()方法在iOS6中已经被废弃(deprecated)

请谨记以下要点:

  1. dispatch_get_current_queue方法在大多数情况下不会如你期望的那样工作。它在iOS 6中已经被废弃了,你只能在用它用于调试
  2. 分发队列以层级结构组织,因此,当前队列不能仅仅用单一队列队形进行描述
  3. 队列指定的数据可以使用dispatch_get_current_queue方法解决常用问题,它能避免由不可重入导致的死锁

47. 熟悉系统框架

48. 循环时优先使用block枚举

请谨记以下要点:

  1. 枚举集合类型总结起来有一共四种方法。使用for循环是最基本的方式,然后是使用NSEnumerator和快速枚举。最现代和先进的方式是使用block枚举方法
  2. block枚举允许你在并发中执行枚举,无需任何额外代码,仅仅使用GCD.在使用其他枚举类型时,你不能这么轻易做到。
  3. 在你知道的情况下,改变块的签名,以便表示精确类型的对象

49.为集合对象使用免费桥(toll-free bridge)

50. 缓存时使用NSCache代替NSDictionary

NSCache是线程安全的

51. 保持初始化和加载实现的依赖

keep initialize and load implementations lean

52. 谨记NSTimer retain它的target

others

栈上的block会被复制到堆上的情况:

  • 调用block的copy实例方法的时候
  • block做为函数返回值的时候
  • 将block赋值给带有__strong修饰符id类型或者block类型的成员变量时
  • 在方法名种含有usingBlock的cocoa框架方法或者GCD的API传递block时

delloc方法中做的事情:

  1. 对于retain的CF对象要CFRelease()
  2. 对于malloc()到堆上的东西要free()掉
  3. 移除通知的observer监听
  4. 移除KVO监听
  5. schedule的timer在这里invalidate
  6. 假如是使用MRC,则需release oc对象
  7. 设置属性的delegate为nil

在ARC工程中手动管理dispatch object的内存(MRR),只要在Xcode 编译器选项-->Custom Compiler flags 中设置 "-DOS_OBJECT_USE_OBJC=0"就可以了

本文地址:https://www.yhawaii.net/effective-objective-c-notes.html
版权声明:本文为原创文章,版权归  所有,欢迎分享本文,转载请保留出处!

 发表评论


表情

  1. Leonardmot
    Leonardmot @回复

    【金合發線上娛樂城】─金合發現金版│電子遊戲│體育賽事投注-最方便最好玩的線上娛樂城

  2. Thomasneife
    Thomasneife @回复

    北歐傢俱- GREEN HOUSE 綠屋家居

  3. ErnestGrere
    ErnestGrere @回复

    台北-中和【均媄醫美診所】─台北微整形、童顏針、玻尿酸最推薦的醫美診所! http://micro-plastic.com/

  4. WilliamNeulk
    WilliamNeulk @回复

    台北市-萬華【禾云室內設計│台北城市工程】─萬華室內設計│萬華裝潢統包│萬華木作工程 http://interior-plan.com/