Blocks
什么时候用Blocks?什么时候用代理?
- 通常的区分方式:如果一个方法或函数的调用只有单一的回调,那么使用
block,如果可能会有多个不同的回调,那么就使用代理。- 这样做的好处是:当一个方法或函数调用会有多种回调的时候,很有可能会有某些回调没有必要实现。代理可以用
@required、@optional关键字做区分;用block处理回调,就会很难区分某个block是否是必须实现的:在Xcode6.3之前,OC 并没有nullable、nonnull等关键字,让我们知道某些方法、某些属性要传入的block可不可以是nil,我们也往往搞不清楚在这些地方传入nil,会不会发生什么危险的事情。__block关键字
- 在
block里面如果使用了在block之外的变量,会将这份变量先复制一份再使用,也就是说,在没有特别宣告的状况下,对我们目前所在的block来说,所有外部变量都是只读取,不能更改。至于block里面用到的 OC 对象,则只会被retain一次。如果想要改变该变量,则需要在该变量前面加上__block关键字。__weak关键字
- 假如某个对象的属性是一个
block而这个block里面又用到了self,就会遇到循环retain而无法释放内存的问题:self要被释放才会去释放这个属性,单这个属性作为block又retain了self,导致self无法被释放。- 如果不想让
block对self retain起来,就需要使用__weak关键字。
Notification Center
- 对象之间可以不必互相知道彼此的存在,也可以相互传递消息、交换资料/状态的机制。
接受通知
一个通知分成几个部分:
object:发送者,是谁发出了这个通知name:这个通知叫什么名字user info:这个通知还带了哪些额外信息
- 在 iOS4 之后,我们可以使用
addObserverForName: object: queue: usingBlock:这组使用block语法的API订阅通知,由于是传入block,所以我们就不必另外又写一个selector。而remove observer的写法也会不太一样,该block语法的API会回调一个observer对象,是对removeObserver:传入之前拿到的observer对象。如下:self.observer = [[NSNotificationCenter defaultCenter]
addObserverForName:NSCurrentLocaleDidChangeNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
// 处理 locale 改变的状态
}];
* `Remove observer`的时候: ```swift [[NSNotificationCenter defaultCenter] removeObserver:self.observ
er];
####发送通知 * 在建立通知对象之后,对通知中心调用`postNotification:`即可。有以下三种方式: ```swift - (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSString *)aName
object:(id)anObject; - (void)postNotificationName:(NSString *)aName
object:(id)anObject
userInfo:(NSDictionary *)aUserInfo;
####通知与线程 * 当我们订阅某个通知之后,我们不能保证负责处理通知的`selector`或`block`会在哪个线程执行 * **这个通知是在哪个线程发出的,负责接受的`selector`或是`block`,就会在哪个线程执行。** * 绝大多数的通知都是在主线程发出。 ####Notification Queue * 程序可能会在短时间内送出大量的通知,而造成资源浪费或效能问题。 * `NSNotificationQueue`相当于是通知发送端与通知中心之间的一个缓冲器,这个缓冲器可以让我们暂缓发出的通知,而在一段缓冲期之内,决定我们是否要合并通知。 > * 首先要建立一个`Notification Queue`对象: > > ```swift > notificationQueue = [[NSNotificationQueue alloc]
initWithNotificationCenter:[NSNotificationCenter defaultCenter]]
;
* 原本: ```swift NSNotification *n = [NSNotification
notificationWithName:@"KKSongInfoDidChangeNotification"
object:self];
[[NSNotificationCenter defaultCenter] postNotification:n];
* 改后: ```swift NSNotification *n = [NSNotification
notificationWithName:@"KKSongInfoDidChangeNotification"
object:self];
[notificationQueue enqueueNotification:n
postingStyle:NSPostASAP
coalesceMask:NSNotificationCoalescingOnName | NSNotificationCoalescingOnSender
forModes:nil];
* 在这边传入了`NSNotificationCoalescingOnName`和`NSNotificationCoalescingOnSender`,代表的就是请`notification queue`合并名称相同,发送者也相同的通知。











网友评论