iOS - block

2019-03-22  本文已影响0人  iOS资深入门

一、简述
block 分类: NSGlobalBlock、NSMallocBlock和NSstackBlock,通过内存的分部部局来分类。
block就是保存一段代码块,想用的时候随时调用。
block 特性:自动捕获变量

    //NSGlobalBlock 全局静态block,不会访问外部局部变量
    void (^block)(void) = ^{
        NSLog(@"hello block");
    };
    block();
    NSLog(@"%@",block); 
    //NSMallocBlock 堆block 保存在堆中的block,当引用计数为0时被销毁。
    int a = 10;
    void (^block)(void) = ^{
        NSLog(@"hello block - %d",a);
    };
    block();
    NSLog(@"%@",block); 
    //NSStackBlock 保存在栈中的block,当函数返回时会被销毁。
    NSLog(@"%@",^{      
        NSLog(@"hello block - %d",a);
    });

二、block的简单使用

//1、作为对象属性
typedef void(^ Myblock)(void);
@property(nonatomic,strong) Myblock block;
//或
@property(nonatomic,strong) void(^block)(void);

//2、作为方法参数
- (void)btnHandler:(void(^)(void))block
{
    block();
}

//3、作为方法返回值。点语法调用、响应式编程
- (void(^)(int))run{
    
    return ^(int m){
        NSLog(@"跑起来,跑了%d米",m);
    };
}
p.run(3);

三、循环引用解决方式

    //方法1
    //只加__weak,在VC被释放后,操作有可能无法完成,在内部加上strong后,可保证操作完成,strongSelf是局部变量,在操作完成出了block作用域后,会被释放,不会引起循环引用
    __weak typeof(self) weakSelf = self;
    self.block = ^{
        __strong typeof(self) strongSelf = weakSelf;
        NSLog(@"%@", strongSelf.title);
    };
    //方法2
    //把self放到局部变量中,self -> block -> vc -> self,在使用完成之后,vc = nil;即可打破循环引用,加__block是为了让vc能在block中被修改。
    __block ViewController * vc = self
    self.block = ^{
        NSLog(@"%@", vc.title);
        vc = nil;
    };
    //方法3
    //传参,参数在操作执行完成,出了block作用域之后,会被释放,打破循环引用。
    @property (nonatomic, copy) void(^block)(ViewController * vc);
    self.block = ^(ViewController * vc){
            NSLog(@"%@",vc.name);
    };
    self.block(self);

四、为什么要给int a加__block,加不加__block有什么区别
1、不加__block,变量a被捕获,为值传递,只读,只可NSLog输出,如果在block内修改a的话,编译器报错。
2、加__block后,是指针传递,可读可写,可对a的值进行修改。

    __block int a = 10;
    void(^block)(void) = ^{
        a++;
    };
    block();

五、block为什么用copy关键字修饰
在MRC下,引入外部变量的block被存放在栈区,出了作用域会被释放,再次调用会造成崩溃。使用copy可以把block拷贝到堆区中,只要对象不销毁,就可以一直调用。

上一篇 下一篇

猜你喜欢

热点阅读