zoukankan      html  css  js  c++  java
  • block的循环引用问题2(block为什么用copy修饰)及处理循环引用

    Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的

    另外需要注意线程安全问题,在调用block时另一个线程有没有可能去修改block如果有, 那就用nomatomic

    比如这样一个Block类型:
    typedef void (^MyBlockType)(int);

    属性声明:
    @property (copy) MyBlockType myBlock;

    这里ARC和非ARC声明都是一样的,当然注意在非ARC下要release Block。

    但是,有了atomic来保证基本的原子性还是没有达到线程安全的,接着在调用时需要把Block先赋值给本地变量,以防止Block突然改变。因为如果不这样的话,即便是先判断了Block属性不为空,在调用之前,一旦另一个线程把Block属性设空了,程序就会crash,如下代码:
    if (self.myBlock)
    {
    //此时,走到这里,self.myBlock可能被另一个线程改为空,造成crash
    //注意:atomic只会确保myBlock的原子性,这种操作本身还是非线程安全的
    self.myBlock(123);
    }

    所以正确的代码是(ARC):
    MyBlockType block = self.myBlock;
    //block现在是本地不可变的
    if (block)
    {
    block(123);
    }

    在非ARC下则需要手动retain一下,否则如果属性被置空,本地变量就成了野指针了,如下代码:
    //非ARC
    MyBlockType block = [self.myBlock retain];
    if (block)
    {
    block(123);
    }
    [block release];

    参考百度知道:iOS block为什么用copy修饰

    处理方法:

    block在copy时都会对block内部用到的对象进行强引用(ARC)或者retainCount增加

    (需要禁止block对self进行强引用或者强制增加引用计数)

    1.ARC:  __weaktypeof(self) weakSelf=self; 其实 __weak someClass *weakSelf = self也是OK的!

    2.MRC:解决方式与上述基本一致,只不过将__weak关键字换成__block即可!

    参考:http://blog.csdn.net/qq_26544491/article/details/46341993

       http://www.cnblogs.com/kesalin/archive/2013/04/30/ios_block.html

  • 相关阅读:
    bzoj3994:[SDOI2015]约数个数和
    数列分块1-9
    luogu P2059 [JLOI2013]卡牌游戏
    luogu P1623 [CEOI2007]树的匹配Treasury
    博弈论与SG函数
    luogu P1169 [ZJOI2007]棋盘制作
    luogu P1623 [CEOI2007]树的匹配Treasury
    [BZOJ4896][THUSC2016]补退选(Trie)
    [BZOJ3745][COCI2015]Norma(分治)
    [BZOJ5006][LOJ#2290][THUWC2017]随机二分图(概率+状压DP)
  • 原文地址:https://www.cnblogs.com/guofuzhang/p/5408278.html
Copyright © 2011-2022 走看看