GCD 以及设计模式
多线程编程
在 iOS 编程中,这几种情况下需要处理多线程:UI 事件必须在主线程里进行,其他的可以放在后台进行;而进行一些耗时长或阻塞线程的任务,最后放进后台线程里进行。iOS 的多线程技术有这么几种:线程,GCD 和 NSOperationQueue。线程这种技术比较复杂,而多线程编程向来是「复杂必死」,推荐尽可能使用后二者,但线程有个后二者没有的优势:能够精确保证任务执行的时间。GCD 全称是 Grand Central Dispatch, 是 libdispatch 这个库的外部代号,基于 C 的底层来实现;而NSOperationQueue,通称操作队列,是基于 GCD 实现的。GCD 能做的 NSOperationQueue 基本上都能做,而且还有些 GCD 中不易实现的特性,如挂起、取消任务,虽然在 iOS 8 中,GCD 也提供了取消任务的功能,但在 GCD 中任务的挂起和取消都有较大的局限性;虽然大多数情况下应该使用抽象级别更高的 API,也就是 NSOperationQueue,但处理一般的后台任务我偏爱 GCD,主要是 GCD 搭配 Blcok 使用简单,非常方便。如何选择,下面两个链接对此问题的讨论值得一看:
StackOverflow: NSOperation vs. Grand Central Dispatch
Blog: When to use NSOperation vs. GCD
另外,还推荐这些文章:objc 的并发编程专题《Concurrent Programming》 及中文翻译版本;雷纯锋的博客《iOS 并发编程之 Operation Queues》;NSHipster 的《NSOperation》。
设计模式
评价 Delegate, Notification, KVO 几种设计模式的优缺点
我不觉得这个问题是个好问题,与其比较这几个设计模式的优缺点,不如谈它们各自的特点比较好,因为它们是为了解决某类问题才设计出来的,有各自适合的使用场景。另外,给个 iOS 中设计模式的介绍:iOS Design Patterns。
为什么出题目都喜欢把这三个设计模式拿来对比呢?Notification 和 KVO都是用于协助对象间的通信:某个对象监听某个事件的发生,当某个事件发生时,该对象会得到通知然后做出响应。这几句话大概是以前看过的书本上说的。如果你以前没接触过设计模式,第一次学习时总是能够看到事件、响应这类模糊的词汇,看得你云里雾里,好吧,我说的是我。 但 delegate,应该说没有监听的功能,而是当事件发生或时机到了,要求 delegate 对象做点什么。刚开始学习 OC 的时候,一本书中将 delegate比喻为助手,那时候不怎么理解,现在觉得这个比喻十分恰当。虽然delegate 模式在 OC 中随处可见,在UIViewController 类中广泛存在,但在开发 FaceAlbum 的过程中只遇到过一次自定义 protocol/delegate 的情况,后来还是用 KVO 取代了。相对于 Notification 和 KVO 模式,使用 delegate 模式你会明确知道对象的 delegate 能干什么,因为要成为 某个对象的delegate,该对象得遵守指定的 protocol,protocol 指定了 delegate 对象需要实现的方法。
Notification和 KVO两者都需要监听事件的对象(早期看见事件就犯晕,如今写来觉得用这个词挺顺手的)去注册,delegate则需要 delegate 对象遵守指定的 protocol;Notification 中监听者向一个单例对象NSNotificationCenter注册,NSNotificationCenter类似一个广播中心,接受任何对象的注册,后者则向要监听的对象注册,一对一,这两者都不需要对象之间有联系,而 delegate 则需要通信的对象通过变量联系;NSNotification模式里监听的对象与被监听的对象通信是通过 NSNotificationCenter 这个中介,而KVO 里,不能说两者是直接通信的,我没有了解过过 KVO 是如何实现通信的,从表面上看两者就那么心灵感应一般,这是系统替我们实现的,而delegate,由于通过变量连接,直接向 delegate 发送消息即可,在这点上,NSNotification不需要通信双方知道对方,而后两者则不然;在响应事件时,NSNotification和 KVO 模式里都是在注册时指定响应方法,而 delegate 则在 protocol 里预定义了响应方法。
说了这么多,不直观,说个实际场景,比如在 UICollectionView 里选择 cell 的时候,希望 title 能够跟踪选中 cell 的数量。这里用NSNotification和 KVO 都能实现,但是我更喜欢 KVO,感觉更优雅,因为使用NSNotification模式的话,选中一个 cell 的时候要在选择的方法里手动发布通知,而 KVO,只要对观察的属性实现 KVO 兼容的方法就可以了;而delegate,自己做自己的 delegate,呃。而面对一些系统里的事件,比如键盘的出现与消失,图片库的变化,使用NSNotification更加自然,因为 KVO 限于对对象属性的跟踪。
暂时写这么多,推荐博客《When to use Delegation, Notification, or Observation in iOS》,可能需要FQ。