美文网首页
iOS block循环引用

iOS block循环引用

作者: tangbin583085 | 来源:发表于2017-09-24 10:25 被阅读0次

    iOS使用block需注意循环应用的问题

    1,一个对象内互相引用

    比如TBViewController2 对象对全局属性block引用,而block内部又引用了TBViewController2 自身对象造成循环引用,内存得不到释放


    BDBC5884-1889-472C-92EF-F88090234FBF.png

    如下代码(Xcode会发出警告, 比较容易发现)

        self.myBlock = ^() {
            [self doSomething];
        };
        myBlock();
    

    又如,Xcode不会放出警告

        void(^myBlock)() = ^() {
            [self doSomething];
        };
        self.myBlock = myBlock;
        myBlock();
    

    解决方案,关键字__weak 修饰self,使block不再持有self

        __weak typeof (self) weakSelf = self;
        self.myBlock = ^() {
            [weakSelf doSomething];
        };
        self.myBlock();
    
    652F3493-5C72-4B5E-985D-390D2B9ED53D.png

    2,多个对象互相引用

    TBViewController2 类实例对象属性持有TBBlockObject对象,TBBlockObject内部属性block又持有了TBViewController2对象,也会造成相互引用,内存得不到释放,而这错种错误编译器很难发现,不会发处警告。

    ![Uploading 111C16BA-7D03-4EDA-8F2C-519AA42823E9_429985.png . . .]

    代码如下:

        TBBlockObject *tbObject = [[TBBlockObject alloc] init];
        self.tbObject = tbObject;
        tbObject.myBlock = ^{
            [self doSomething];
        };
    

    解决方案: __weak 修饰TBViewController2 self对象,使block不再持有TBViewController2 self对象:

        TBBlockObject *tbObject = [[TBBlockObject alloc] init];
        self.tbObject = tbObject;
        __weak typeof (self) weakSelf = self;
        tbObject.myBlock = ^{
            [weakSelf doSomething];
        };
    
    111C16BA-7D03-4EDA-8F2C-519AA42823E9.png

    3,绝大部分GCD都不会产生循环引用

    因为对象(TBViewController2)本身并没有对block进行持有,所以不会产生循环引用。

        // CGD 绝大部分都不会产生循环引用
        dispatch_async(dispatch_get_main_queue(), ^{
            [self doSomething];
        });
    

    下列代码会产生循环引用

        // 如果对对象本身对 block持有,也会出现循环引用
        void(^myBlock)() = ^{
            [self doSomething];
        };
        self.myBlock = myBlock;
        dispatch_async(dispatch_get_main_queue(), myBlock);
    

    解决方案,原理同上,利用__weak不让对象block持有对象本生

        // 如果对对象本身对 block持有,使用weakSelf
        __weak typeof (self) weakSelf = self;
        void(^myBlock)() = ^{
            [weakSelf doSomething];
        };
        self.myBlock = myBlock;
        dispatch_async(dispatch_get_main_queue(), myBlock);
    

    4,2个对象拥有同一个block

    假设TBViewController2对象和TBBlockObject同时拥有同一个block, 而block里面持有对象TBViewController2,但是某个时刻TBViewController2释放了,就会导致在运行TBBlockObject的block的时候出错。

        TBBlockObject *tbBlockObject = [[TBBlockObject alloc] init];
        self.tbBlockObject = tbBlockObject;
        
        TBViewController2 *vc2 = [[TBViewController2 alloc] init];
        // 注意weak,否则会循环引用
        __weak typeof(vc2) weakVC2 = vc2;
        void(^myBlock)() = ^() {
            [weakVC2 doSomething];
        };
        
        // 赋值block
        vc2.myBlock = myBlock;
        tbBlockObject.myBlock = myBlock;
        
        // 执行
        vc2.myBlock();
        tbBlockObject.myBlock();
        
        [self.navigationController pushViewController:vc2 animated:YES];
    

    当退出vc2的时候,再执行

        [self.tbBlockObject excuteTBBlockObject];
    

    就会出错了(无输出日志)

    相关文章

      网友评论

          本文标题:iOS block循环引用

          本文链接:https://www.haomeiwen.com/subject/byznsxtx.html