【问题标题】:Weak Self in Blocks块中的弱自我
【发布时间】:2015-06-17 15:45:44
【问题描述】:

我是否需要检查弱自我是否在块中为零?

我创建了weakSelf指针,如:

__weak typeof(self) weakSelf = self;

在我做的块的开头

if(!weakSelf){return;}

这是不必要的吗?还是取决于我是否正确编码了其余部分,以便当自己死去时,其他人也会死去?

【问题讨论】:

  • 这取决于你的块应该做什么。一般来说,如果你想确保块只在 wealSelf 不为零时执行,那么你需要那行!
  • 基本上任何方法调用都是Obj-C中nil指针上的有效操作数,所以不需要检查;像例如如果weakselfnil,那么这样的方法调用不会在您的块中引起任何问题:[weakself doSomething];

标签: ios objective-c weak-references weak-ptr


【解决方案1】:

该检查是不必要的,并且会给您一种虚假的安全感。

问题来了:

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    if (!weakSelf) { return; }
    // THE LINE OF INTEREST
    [weakSelf doSomething];
});

THE LINE OF INTEREST,其他一些线程可能会清除对self 的最后一个强引用,此时weakSelf 被设置为nil。所以doSomething 消息被发送到 nil,这是“安全的”(它什么都不做),但可能不是你所期望的!

如果你想在weakSelf 为 nil 时采取不同的操作,那就更糟了,例如

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    if (weakSelf) {
        [weakSelf doSomething];
    } else {
        [someOtherObject doSomethingElse];
    }
});

在这种情况下,在块验证 weakSelf 不是 nil 和发送 doSomething 消息之间,weakSelf 可能变为 nil,doSomethingdoSomethingElse 都不会实际运行.

正确的解决办法是这样的:

__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    typeof(self) strongSelf = weakSelf;
    if (strongSelf) {
        [strongSelf doSomething];
    } else {
        [someOtherObject doSomethingElse];
    }
});

在这种情况下,将weakSelf 复制到strongSelf(默认为强)是原子操作。如果weakSelf 为零,strongSelf 将为零。如果 weakSelf 不是 nil,strongSelf 将不会是 nil,并且将是对该对象的强引用,防止它在 doSomething 消息之前被释放。

【讨论】:

  • 在您的代码中可以简单地使用self 而不是weakSelf
  • 如果你直接在块中使用self,块会强烈捕获self,使其保持活动状态。如果使用weakSelf,该块不会强捕获self,并允许在块运行之前释放它。
  • 没错。所以物体的寿命更长。只要块需要被执行。通常这正是您想要的。
  • 但有时并非如此。 “只使用self 而不是weakSelf”的建议需要加以限定:有时它会改变程序的行为。此外,在无限期保存块的情况下,它可以创建一个保留周期。这不会在我的答案代码中发生,但一些常用的 API(如NSNotificationCenter)确实会无限期地保存块。 EralpB 没有显示他创建块的上下文。他的用例可能需要避免保留周期。
  • 我没有直接说:“只需使用self 而不是weakSelf。”我说:“在您的代码中,可以简单地使用 self 而不是弱自我”。因此,没有理由为不属于讨论主题的事物寻找示例。
【解决方案2】:

这似乎完全没有必要,因为在 nil 上调用消息是无操作的。 (什么都没有发生)

^{
    [weakSelf doSomething]; //Does nothing if weakSelf is nil
}

我认为您可能想要这样做的唯一原因是不应该调用 other 消息(不是关于自己)

^{
    // Here I don't want to add weakSelf as an observer if it's nil
    if (!weakSelf) return;

    [OtherClass addObserverForSomething:weakSelf];
}

【讨论】:

    【解决方案3】:

    弱引用不保留被引用的对象。如果没有其他人保留它,则释放该对象并且弱引用引用nil

    因此,您的代码可能会使用引用nilweakSelf 执行。但这根本不是检查它的理由。特别是在 Objective-C 中,如果您发送消息 nil,您会使用已定义的行为。 IE。如果您使用nil 引用设置属性,这是完美的代码。它只是无处可去。

    当然有时您不想与nil 互动。在这种情况下,您必须检查它。

    顺便说一句:您只在某些情况下需要weakSelf,很少见。这是一个都市传说,在闭包中对self 的一般引用必须很弱以防止保留循环。这不是真的,不是真的,也永远不会是真的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-10
      • 1970-01-01
      • 2016-11-25
      • 1970-01-01
      • 2017-12-23
      • 2014-08-19
      • 1970-01-01
      相关资源
      最近更新 更多