【问题标题】:when weakSelf will be nil in block ,when should add strongSelf当weakSelf在block中为nil时,什么时候应该添加strongSelf
【发布时间】:2017-01-24 07:47:13
【问题描述】:

通过在块中使用weakSelf,您可以避免保留循环。但有时您应该保持weakSelf直到块保留,因此您需要像使用strongSelf一样

__weak __typeof__(self) weakSelf = self;
dispatch_group_async(_operationsGroup, _operationsQueue, ^
{
__typeof__(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doSomethingElse];
} );

我想知道weakSelf什么时候为nil,那么我们应该添加__strong typeof(self) strongSelf = weakSelf

【问题讨论】:

  • self 已经很强大了。你有弱有强,两者之间没有任何关系。
  • 如果只是在 'self' 持有的块中使用 'self' ,导致保留循环。因此你应该使用 weakSelf 。StrongSelf 是对 self 的强引用,但是当块完成时它将被释放。就这样不要导致保留循环。(只是我的理解)

标签: ios objective-c


【解决方案1】:

例如:如果你的阿姨问你,“请在我起飞前从市场购买雨伞”。你去了市场,很难找到一把雨伞。几个小时后,你终于找到了一把漂亮的雨伞,然后你回到家,但你发现你的阿姨已经离开了,你感觉很糟糕。但这对你阿姨来说是正确的,因为飞行比雨伞更重要。

但是在您的编码问题中,您要做的是 你正在逛市场,带着你姑姑的护照,这样她就不会离开,直到你回来。

我想这很粗鲁,但如果你仍然想这样做,请使用 self 而不是 strongSelf

dispatch_group_async(_operationsGroup, _operationsQueue, ^
{
  [self doSomething];
  [self doSomethingElse];
} );

【讨论】:

  • 这种情况下不能使用 weakSelf 。但是有时您需要使用 weakSelf 来保持循环。如果需要使用strongSelf来避免weakSelf被释放,那么程序可能会出错。
  • My reference 对吗?
【解决方案2】:

这一切都取决于您的要求。没有人,正确的答案。

捕获self 微弱地允许释放实例,即使该块仍保留在某处。如果self在块执行之前被释放,那么它就是块内的nil

如果在 self 已被释放时块不应该做任何事情,则没有理由强烈捕获 self。只需测试nil 并提前退出。或者在不作用于self 的块中做任何需要的工作。

如果self 在块执行之前不应该消失,则强烈捕获self,但通过确保self 没有对该块的强引用来避免保留循环。

如果self 在块开始执行之前消失是可以的,但必须一直停留直到块完成,块应该在开始时捕获对弱捕获的self 的强引用。

【讨论】:

  • 在我的情况下,'self' 必须坚持直到块完成。什么情况下使用 strongSelf 或必须使用 strongSelf?
【解决方案3】:

如果问题是:“weakSelf 何时为零”。

答案是:当没有人拥有 self 的实例时

例如,您有一个名为 vcUIViewController 实例,vc 有一个名为 apiHandler 的查询 API 依赖项,而 api 有一个名为 successCallback 的回调块。

像这样:

@interface ApiHandler: NSObject

@property (nonatomic, copy) void (^successCallback)();

@end



@interface vc : UIViewController

@property (nonatomic, strong) ApiHandler *apiHandler;

@end

@implementation vc

- (void)doQuery {
    self.apiHandler.successCallback = ^{
        [self doSomething];
    };
}

- (void)doSomething {

}

如果vc 被弹出或关闭,vc 实例不会 解除分配。因为保留周期。

vc拥有apiHandlerapiHandler拥有successCallbacksuccessCallback拥有vc

因此,在块中使用 weak vc 可以避免保留循环。

像这样:

- (void)doQuery {
    __weak __typeof__(self) weakSelf = self;

    self.apiHandler.successCallback = ^{
        [weakSelf doSomething];
    };
}

现在,如果您的vc 被弹出或关闭,vc 实例将被释放,而 weakSelf 将为 nil

apiHandler在后台线程查询成功并调用successCallback,消息doSomething将发送到nil对象。 (僵尸)

这就是为什么你需要像你说的那样在块中使用 strongSelf。

【讨论】:

  • 如你所说,只有 self 被释放,weakSelf 将为零。我的理解是对的?
  • @anjingpan,是的,没错。所以如果你能确定self不会被dealloc,直接使用self就可以了。但要小心保留周期。
  • @anjingpan,顺便说一句,您可以使用libextobjc 简化代码。只需@weakify(arg)@strongify(arg) 就可以为所欲为,而且非常清楚。
猜你喜欢
  • 2017-12-17
  • 2020-11-02
  • 1970-01-01
  • 1970-01-01
  • 2019-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-16
相关资源
最近更新 更多