前言

NSObject 属于 Foundation 框架,我们写的OC代码全部都是基于这些基本系统框架之上的

笔记

熟悉系统框架

  1. 将一系列代码封装为动态库,并在其中放入描述其接口的头文件,这样做出来的东西就叫框架。所有iOS平台的系统框架都是动态库
  2. NS开头的基本都是Foundation框架,与Foundation框架对应的一个CoreFoundation框架,他是C语言的API
  3. 使用toll-free bridging可以实现Foundation的OC对象和CoreFoundation的C数据结构互相转换
  4. 使用C语言的API可以绕过OC的runtime机制,加快运行速度;但是使用C语言的API时,需要注意内存管理的问题

多用块枚举,少用for循环

  1. 使用OC1.0的 NSEnumerator 来遍历

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    NSArray *array = /*...*/;
    NSEnumerator *enumerator = [array objectEnumerator];
    id object;
    while ((object = [enumerator nextObject]) != nil) {
    // do something
    }

    NSDictionary *dict = /*...*/;
    NSEnumerator *enum = [dict keyEnumerator];
    id key;
    while ((key = [enum nextObject]) != nil) {
    id value = dict[key];
    // do something
    }
  2. 框架还提供反向遍历的enum接口

  3. 使用OC2.0的 快速遍历 ,也就是for in

  4. 基于块的遍历方式,对于NSArray有-(void)enumerateObjectsUsingBlock:(void(^)(id object, NSUinteger idx, BOOL *stop))block; ;其他的collection也有相对应的方法。使用block方法,可以获取更多的信息

对自定义其内存管理语义的collection使用无缝桥接

  1. 使用无缝桥接来转换Foundation和CoreFoundation

    1
    2
    NSArray *array = @[@1, @2, @3];
    CFArrayRef aCFArray = (__bridge CFArrayRef)array;
  2. __bridge 还有疑问

  3. NSDictionary 对于key是copy,对于value则是retain。要想改变期内存语义的话呢,只能使用CoreFoundation了,具体的看书~

构建缓存时选用NSCache而非NSDictionary

  1. NSCache在系统低内存时会自动删减缓存,而且优先删减的是最长时间没有使用过的缓存
  2. NSCache的key是retain的,不是copy的。因为很多时候,这个key的对象不支持copy
  3. 线程安全,这点对于缓存来说很关键

精简initialize与load的实现代码

  1. + (void)load; 每个类必定会调用该方法,而且仅调用一次。当包含类的程序库载入系统时,就会执行此方法,也就是程序启动的时候
  2. 如果分类和类都定义了load方法,那么先调用类的,再调用分类的
  3. 在执行类的的load之前,会先执行多有超类的load方法
  4. load方法和其他不一样,如果子类没有实现的话,不管超类有没有,他都不会继承该方法
  5. load方法要精简,程序在执行没有load方法的时候都会阻塞
  6. 尽量不要使用load方法
  7. + (void)initialize; 在程序第一次使用这个类的时候,会调用该方法。它也只会运行一次。不应该由代码来显式调用。
  8. initialize只有在程序用到该类的时候才会调用,属于惰性调用;它由运行期系统来调用。调用它的时候,系统中的个各类都是可以正常使用的,这一点和load方法不同

别忘了NSTimer会保留其目标对象