kkbox-ios-dev笔记(五) - Block/Notification

Blocks

什么时候用Blocks?什么时候用代理?

  • 通常的区分方式:如果一个方法或函数的调用只有单一的回调,那么使用block,如果可能会有多个不同的回调,那么就使用代理。
  • 这样做的好处是:当一个方法或函数调用会有多种回调的时候,很有可能会有某些回调没有必要实现。代理可以用@required@optional关键字做区分;用block处理回调,就会很难区分某个block是否是必须实现的:在Xcode6.3之前,OC 并没有nullablenonnull等关键字,让我们知道某些方法、某些属性要传入的block可不可以是nil,我们也往往搞不清楚在这些地方传入nil,会不会发生什么危险的事情。

__block关键字

  • block里面如果使用了在block之外的变量,会将这份变量先复制一份再使用,也就是说,在没有特别宣告的状况下,对我们目前所在的block来说,所有外部变量都是只读取,不能更改。至于block里面用到的 OC 对象,则只会被retain一次。如果想要改变该变量,则需要在该变量前面加上__block关键字。

__weak关键字

  • 假如某个对象的属性是一个block而这个block里面又用到了self,就会遇到循环retain而无法释放内存的问题:self要被释放才会去释放这个属性,单这个属性作为blockretainself,导致self无法被释放。
  • 如果不想让blockself 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`合并名称相同,发送者也相同的通知。

你可能感兴趣的:(kkbox-ios-dev笔记(五) - Block/Notification)