iOS和ARC:如何在异步操作期间保留self?

F.X*_*.X. 17 objective-c ios automatic-ref-counting

这是我第一次摆弄iOS5和ARC.到目前为止,这么好,它有效,但我遇到了某种问题.

我有一个自定义UIStoryboardSegue,我使用Facebook Connect(或其他服务)将用户登录到我的应用程序.简而言之,它应该做到以下几点:

  1. 用户点击按钮
  2. 按钮点燃了Segue
  3. segue启动异步登录,但不会立即推送视图控制器
  4. 如果且仅当登录成功时,segue才会推送视图控制器

相反,是登录开始,但是在有机会完成之前,ARC会立即释放segue.

我想到了一个快速的黑客来阻止这个:

@interface BSLoginSegue() {
    __strong BSLoginSegue *_retained_self;
}
@end

// Stuff...
// Other stuff...

- (void) perform {
    login();
    _retained_self = self;
}

- (void) loginServiceDidSucceed:(BSLoginService *)svc {
    ...
    _retained_self = nil;
}
Run Code Online (Sandbox Code Playgroud)

问题是,它真的一个黑客,所以我想知道是否还有其他更优雅的方式我可以做同样的事情?

jha*_*ott 8

如果您使用Grand Central Dispatch(GCD)进行并发(您应该这样做,那真棒!)然后通过在Objective-C块中对对象进行引用并将其传递给GCD,它将被块自动保留,直到之后该块已执行并已自行释放.

如果不确切知道你是如何进行异步操作的话,很难给出明确的答案,但是通过使用GCD,您根本不必担心这一点.该块将负责保留它引用的对象,ARC将完成其余的工作.

看起来你必须在UIStoryboardSegue某个地方存储对你的子类的引用,以便调用loginServiceDidSucceed:它,所以也许只是让它成为一个强引用.再次,从(例如登录成功时的完成块)引用它是理想的.我建议调整您的登录代码以使用块来进行成功/失败回调.


isa*_*aac 3

类应该需要保留自身的想法表明可能存在设计问题。当一个对象保留自身时,就不清楚谁拥有它或谁可能引用它,并且泄漏的风险很高。

哪个类负责呈现 segue?它与包含按钮的类是同一个类吗?这个类应该保留segue,呈现segue,然后在segue完成时释放segue。

如果不进一步深入了解视图控制器层次结构,就很难给出具体的建议。但我的第一反应是建议决定是否呈现 Segue 的视图控制器应该在 Segue 上具有强大的属性。子类化的 segue 可以定义一个协议,呈现类可以遵守该协议,以告知何时应该取消/释放 segue。