iOS开发笔记-Block

Block 实际上就是 Objective-C 语言对于闭包的实现。对于 Block 的基本认识和使用,这里推荐一个博客 iOS开发-由浅至深学习block ,这里不在多做过多的描述.本文主要讲关于Blockweak-strong dance.

weak-strong dance

使用 Block 时可以通过__weak来避免循环引用已经是众所周知的事情:

// OCClass.m

__weak typeof(self) weakSelf = self;
self.handler = ^{ NSLog(@"Self is %@", weakSelf); };

这时handler持有 Block 对象,而 Block 对象虽然捕获了weakSelf,延长了weakSelf这个局部变量的生命周期,但weakSelf是附有__weak修饰符的变量,它并不会持有对象,一旦它指向的对象被废弃了,它将自动被赋值为nil。在多线程情况下,可能weakSelf指向的对象会在 Block 执行前被废弃,这在上例中无伤大雅,只会输出Self is nil,但在有些情况下(譬如在 Block 中有移除KVO的观察者的逻辑,在执行到该逻辑前 self 就释放了)就会导致 crash。这时可以在 Block 内部(第一句)再持有一次weakSelf指向的对象,保证在执行 Block 期间该对象不会被废弃,这就是所谓的 weak-strong dance

__weak typeof(self) weakSelf = self;
self.handler = ^{
    typeof(weakSelf) strongSelf = weakSelf;
    // ...
    [strongSelf.obserable removeObserver:strongSelf
                              forKeyPath:kObservableProperty];
};

typeof(weakSelf) strongSelf = weakSelf这一句等于__strong typeof(weakSelf) strongSelf = weakSelf,在 ARC 模式下,id 类型和 OC 对象类型默认的所有权修饰符就是__strong,所以是可以省略的。

顺便说一下,__weak修饰的变量不会持有对象,它用一张 weak 表(类似于引用计数表的散列表)来管理对象和变量。赋值的时候它会以赋值对象的地址作为 key,变量的地址为value,注册到 weak 表中。一旦该对象被废弃,就通过对象地址在 weak 表中找到变量的地址,赋值为 nil,然后将该条记录从 weak 表中删除。

你可能感兴趣的:(iOS开发笔记-Block)