【问题标题】:What is the difference between a __weak and a __block reference?__weak 和 __block 引用有什么区别?
【发布时间】:2012-07-31 04:20:52
【问题描述】:

我正在阅读 Xcode 的文档,这让我感到困惑:

__block typeof(self) tmpSelf = self;
[self methodThatTakesABlock:^ {
    [tmpSelf doSomething];
}];

以下内容来自文档:

块形成对其捕获的变量的强引用。如果你使用 self 在一个块内,该块形成一个对self 的强引用,所以如果 self 还具有对块的强引用(通常 确实),一个强大的参考循环结果。为了避免循环,您需要 在块外创建对 self 的弱(或__block)引用,如 在上面的例子中。

我不明白“弱(或__block)”是什么意思?

__block typeof(self) tmpSelf = self;

__weak typeof(self) tmpSelf = self;

这里一模一样?

我在文档中发现了另一篇文章:

注意:在垃圾收集环境中,如果您同时应用 __weak__block 对变量进行修饰符,则该块将无法确保它保持活动状态。

所以,我完全感到困惑。

【问题讨论】:

    标签: objective-c memory-management objective-c-blocks weak-references ownership


    【解决方案1】:

    来自关于 __block 的文档

    __block 变量存在于变量的词法范围和在变量的词法范围内声明或创建的所有块和块副本之间共享的存储中。因此,如果在帧中声明的块的任何副本在帧结束后仍然存在(例如,通过在某处排队以供稍后执行),则存储将在堆栈帧的破坏中幸存下来。给定词法范围内的多个块可以同时使用一个共享变量。

    来自关于 __weak 的文档

    __weak 指定一个不使被引用对象保持活动状态的引用。当对象没有强引用时,弱引用设置为 nil。

    所以它们在技术上是不同的东西。 __block 是为了阻止你的变量从你的外部作用域复制到你的块作用域。 __weak 是一个自定界的弱指针。

    注意我说的是技术性的,因为对于你的情况,他们会(几乎)做同样的事情。唯一的区别是您是否使用 ARC。如果您的项目使用 ARC 并且仅适用于 iOS4.3 及更高版本,请使用 __weak。如果全局范围引用以某种方式释放,它确保引用设置为 nil。如果您的项目不使用 ARC 或适用于较旧的操作系统版本,请使用 __block。

    这里有一个细微的差别,请确保你理解它。

    编辑:另一个难题是__unsafe_unretained。此修饰符与 __weak 几乎相同,但适用于 4.3 之前的运行时环境。但是,它没有设置为 nil,并且可能会给您留下悬垂的指针。

    【讨论】:

    【解决方案2】:

    在手动引用计数模式下,__block id x;具有不保留 x 的效果。在 ARC 模式下,__block id x;默认保留 x (就像所有其他值一样)。要获得 ARC 下的手动引用计数模式行为,您可以使用 __unsafe_unretained __block id x;。然而,正如名称 __unsafe_unretained 所暗示的那样,拥有一个非保留变量是危险的(因为它可能会悬空),因此不鼓励使用。两个更好的选择是使用 __weak(如果您不需要支持 iOS 4 或 OS X v10.6),或者将 __block 值设置为 nil 以中断保留周期。

    apple docs

    【讨论】:

      【解决方案3】:

      除了__block__weak 的其他答案之外,还有另一种方法可以避免您的场景中的保留周期。

      @weakify(self);
      [self methodThatTakesABlock:^ {
          @strongify(self);
          [self doSomething];
      }];
      

      More Info about @Weakify @Strongify Macro

      【讨论】:

        【解决方案4】:

        在block中使用self时,应该使用__weak,而不是__block,因为它可能会保留self。

        如果你需要强大的自我,那么你可以这样使用:

        __weak typeof(self) *weakSelf = self;
        [self methodThatTakesABlock:^{
            if (weakSelf) {
                __strong typeof(self) *strongSelf = weakSelf;
                [strongSelf doSomething];
            }
        }];
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-05
          • 2010-09-30
          • 2012-01-25
          • 1970-01-01
          • 2011-04-09
          相关资源
          最近更新 更多