kkbox-ios-dev笔记(五) - Block/Not
2017-03-17 本文已影响26人
百草纪
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`合并名称相同,发送者也相同的通知。