一.Block基础

语法

block是Objective-C上用来实现匿名函数的特性的一种技术。它是一种特殊的Objective-C对象,实际效果就是一段代码块的回调引用。它主要有几个特点:

  • block的代码是内联的,效率高于函数调用。
  • block对于外部变量默认是只读属性。
  • block被Objective-C看成是对象处理

Block变量的声明格式为: 返回值类型(^Block名字)(参数列表)

Block变量的定义格式为: Block变量 = ^(参数列表){函数体}

typedef 返回值类型(^Block名字)(参数列表)

基本用法

Block 可以捕获来自外部作用域的变量,这是Block一个很强大的特性。默认情况下,Block 中捕获的到变量是不能修改的,如果想修改,需要使用__block进行声明:

- (void)testFuc(){
    __block int a = 10;
    void (^testBlock)(void) = ^{
        a = 42;
        NSLog(@"int a:%i",a);//最后打印int a:42
    }
    testBlock();
}

高级用法

  • 在非 ARC 的情况下,对于 block 类型的属性应该使用copy,因为 block 需要维持其作用域中捕获的变量。
  • 在 ARC 中编译器会自动对 block 进行 copy 操作,因此使用strong或者copy都可以,没有什么区别,但是苹果仍然建议使用copy来指明编译器的行为。
  • block 在捕获外部变量的时候,会保持一个强引用,当在 block 中捕获self时,由于对象会对 block 进行copy,于是便形成了引用循环。

由于block的属性是copy的,所以也解释了从block外部捕获的变量是不能修改的且是强引用的。避免循环引用的方法一般是声明一个__weak的临时变量。

typedef (^testBlock)(void)
@interface Test : NSObject
@property (nonatomic, copy) testBlock completeHandle;
@end

@implementation
- (void)configureBlock {
    __weak typeof(self) weakSelf = self;//使用weakSelf的话,不能保证weakSelf在block执行的时候不是nil。
    self.completeHandle= ^{
        __strong typeof(weakSelf) strongSelf = weakSelf;//使用strongSelf能保证在block内部执行的时候不是nil。
        [strongSelf doSomething];
        [strongSelf doMoreThing];
    };
}
为什么有可能 block 执行的过程当中 weakSelf 变为 nil?

weak置 nil 的操作发生在 dealloc 中,最后一个持有 object 的对象被释放的时候,会触发对象的 dealloc,而这个持有者的释放操作就不一定保证发生在哪个线程了。因此 block 执行的过程中 weakSelf 有可能在另外的线程中被置为 nil。

简而言之,在多线程环境下weak是无法保证在确定的线程中被置为nil的,可能导致在block执行中对象的上下文不一致。

results matching ""

    No results matching ""