52个有效方法阅读笔记(六)

1.熟悉系统框架

  • 将一系列代码封装成动态库(dynamic library),并在其中放入描述其接口的头文件,这样做出来的东西就叫框架.

  • 系统的一些常见框架:

  • CFNetwork 此框架提供了 C 语言级别的网络请求,它将"BSD 套接字"(BSD socket)抽象成易于使用的网络接口.

  • CoreAudio 该框架所提供的 C 语言 API 可用来操作设备上的音频硬件.

  • AVFoundation 此框架所提供的 Objective-C 对象可用来回放并录制音频及视频,比如能够在 UI 视图类里播放视屏.

  • CoreData 此框架所提供的 Objective-C 接口可以将对象放入数据库,便于持久化保存.

  • CoreText 此框架提供的 C 语言接口可以高效执行文字排版及渲染操作.

  • 许多系统框架都可以直接使用.其中最重要的是 Foundation 与 CoreFoundation, 这两个框架提供了构建应用程序所需要的许多核心功能.

  • 请记住:用纯 C 写成的框架与用 Obecjtive-C 写成的一样重要,若想成为优秀的 Objective-C 开发者,应该掌握 C 语言的核心概念.

2.多用块枚举,少用 for 循环

  • for 循环,这是最基本的循环方法,因而功能也非常有限.
  • 使用 Objective-C1.0的 NSEnumerator 来遍历: NSEnumerator是个抽象类,提供了两个方法
- (NSArray *)allObejcts
- (id)nextObject
  • 快速遍历, for in :如果某个类的对象支持快速遍历,那么就可以宣城自己遵从了名为 NSFastEnumerator 的协议,从而开发者可以采用次语法来迭代该对象.此协之定义了一个方法:
- (NSUInteger)countByEnumeratingWithState:
               (NSFastEnumerationSate *)state
               object:(id *)stackbuffer
                count:(NSUInteger)length
  • 基于块的遍历方式:此方法大大胜于其他方式的地方在于:遍历时可以直接获取更多信息.
  • 遍历 collection 有四种方法.最基本的办法就是 for 循环,其次是NSEnumerator 遍历法及快速遍历法,最新,最先进的方式是"块枚举法".
  • "块枚举法"本身就能通过 GCD 来并发执行遍历操作,无需另行编写代码.而采用其他遍历方法则无法轻易实现这一点.
  • 若提前知道呆遍历的 collection 含有的何种对象,则应该改块签名,指出对象的具体类型.这样编译器就可以检测出开发者是否调用了该对象不具备的方法,并在发现这种问题时报错.

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

  • 使用"无缝桥接(toll-free-bridging)"技术,可以在定义与 Foundation 框架中的 Obejctive-C 类和定义 CoreFoundation 框架中的 C 数据结构之间互相转换.
  • __brige 本身的意思是: ARC 仍然具备这个 Obejctive-C 对象的所有权,而 __bridge retained 则相反,意味着 ARC 将交出对象的所有权.
  • 在 CoreFoundation 层面创建 collection 时,可以指定许多回调函数,这些函数表示此 collection 应如何处理其元素.然后,可运用无缝桥接技术,将其转换成具备特殊内存管理语义的 Objective-C collection.

4.构建缓存时选用 NSCache而非 NSDicationary

  • NSCache 胜过 NSDictionary 之处于,当系统资源将要耗尽时,它可以自动删减缓存. NSCache 会先行删减"最久未使用的(lease recently used)"对像.
  • 实现缓存时应选用 NSCache 而并非 NSDicationary 对象,因为 NSCache 可以提供优雅的,自动删减功能,而且是"线程安全的",此外,它与字典不同,并不会拷贝键.
  • 可以给 NSCache 对象设置上限,用以限制缓存中的对象总个数及"总成本",而这些尺度则定义了缓存删减其中对象的时机.但是绝对不要把这些尺度当成可靠的"硬限制(hard limit)",它们仅对 NSCache 起指导作用.
  • 如果缓存使用得当,那么应用程序的响应速度就能提高.只有那种狗"重新计算起来费事"数据,才值得放入缓存,比如那些需要从网络获取或从磁盘读取的数据.

5.精简 initialize 与 load 的实现方法

    • (void)load 对于加运行系统的每个类(class)和分类(catergory)来说,必定会调用此方法,而且仅调用一次.
  • initialize 方法只应该用来设内部数据,不应该在其中调用其他方法,即便是本类方法,也最好不要调用.
  • 在加载阶段,如果实现了 load 方法,那么系统会调用它.分类也可以定义此方法,类的 load 方法要比分类的先调用.去其他方法方法不同, load 方法不参与覆写机制.
  • 首次使用某个类之前,系统会向其发送 initialize 消息.由于此方法遵循普通的覆写规则,所以通常应该在里面判断当前要初始化的是那个类.
  • load 与 initialize 方法都应该实现得精简一些,这有助于应用程序的响应能力,也能减少引入"依赖环(interdependency cycle)"的几率.
  • 无法在编译期设定的全局变量,可以放在 initialize 方法里面设置.

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

  • 计时器要和"运行循环(run loop)"相关联,运行循环到时候回触发任务.创建NSTimer 时,可以将其"预先安排"在当前的运行循环中,也可以先创建好,然后由开发者自己来调度.
  • NSTimer对象会保留其目标对象,直到计时器失效为止,调用 invalidate 方法可令计时器失效,另外,一次性的计时器在触发完任务后也会失效.
  • 反复执行任务的计时器(repeating timer),很容易引入保留环,如果这种计时器的目标对象又保留了计时器本身,那肯定会导致保留环.真阳环状保留关系,可能是直接发生的,也可能是通过对象图里的其它对象间接发生的.
  • 可以扩充 NSTimer 的功能,用"块"来打破保留环.不过,除非 NSTimer 将来在公共接口里提供此功能,否则必须创建分类,将相关实现代码加入其中.

你可能感兴趣的:(52个有效方法阅读笔记(六))