zoukankan      html  css  js  c++  java
  • iOS: 属性声明strong和retain竟然不一样

    今天和同事在处理一处用strong声明的Block属性引发的问题时偶然发现的。在诸多教程中都会讲到:声明属性时用strong或者retain效果是一样的(貌似更多开发者更倾向于用strong)。不过在声明Block时,使用strongretain会有截然不同的效果。strong会等于copy,而retain竟然等于assign

    当然定义Block还是应该用copy(还有其他需要注意的地方,可以参考这篇文章:iOS: ARC和非ARC下使用Block属性的问题),因为非ARC下不copy的Block会在栈中,ARC中的Block都会在堆上的。

    可以这样复现问题。在非ARC环境下,定义一个简单类型,定义一个Block属性,先用正确的copy

    1 @interface TestCls : NSObject
    2 
    3 @property (nonatomic, copy) void(^myBlock)();
    4 
    5 @end

    在另一个类型里声明变量:

     1 TestCls *_testObj 

    然后在一个方法里,比如viewDidLoad中,设置Block变量,注意即便是在非ARC下,没有引用外部变量的Block类型也是__NSGlobalBlock__,而引用外部变量的Block才是__NSStackBlock__,如下代码:

    1 _testObj = [[TestCls alloc] init];
    2 
    3 int outerVar = 12;
    4 
    5 _testObj.myBlock = ^void()
    6 {
    7     NSLog(@"Block被调用:%d", outerVar);
    8 };
    9 NSLog(@"Block类型:%@", [_testObj.myBlock class]);

    然后在另一个方法里(比如UIButton的点击事件方法里)去执行Block,如下:

     1 _testObj.myBlock();  

    测试环境是Xcode 6/iOS 7/8,如果最上面myBlock属性声明是copy或者strong的话,Block都会被copy,输出:

     Block类型:__NSMallocBlock
    __ Block被调用:
    12
     

    如果上面myBlock属性声明是retain或者assign的话,Block表现起来就是assign,没有去copy,输出:

     Block类型:__NSStackBlock__ 

    此时可能会Crash(BAD_ACCESS),也有可能输出错误的值(我在控制台下测试会出现这种情况)。因为Block作用域在函数栈里,而函数已经执行完毕了。 

    总之,strongretain竟然有不一样的地方,而声明Block属性请务必用copy

  • 相关阅读:
    xmind等工具下载
    remix使用经验积累
    visual studio code下载地址
    以太坊存储类型(memory,storage)及变量存储详解
    remix共享本地文件夹教程
    在remix恢复已部署的合约步骤
    ERC721 相关语法和知识点学习
    用truffle写测试用例
    truffle环境搭建和应用
    jenkins pipeline基础语法与示例
  • 原文地址:https://www.cnblogs.com/fengmin/p/5390073.html
Copyright © 2011-2022 走看看