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

时间:2012-05-09 15:03:58

标签: objective-c ios automatic-ref-counting

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

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

  1. 用户点击按钮
  2. 按钮触发Segue
  3. segue启动异步登录但不立即推送视图控制器
  4. 如果且仅当登录成功时,segue才会推送视图控制器
  5. 相反,登录是否开始,但是在有机会完成之前,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;
    }
    

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

4 个答案:

答案 0 :(得分:8)

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

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

看起来您必须在某个地方存储对UIStoryboardSegue子类的引用,以便在其上调用loginServiceDidSucceed:,因此可能只需要使用强引用即可。再一次,从block引用它(例如登录成功时的完成块)是理想的。我建议调整您的登录代码以使用块来进行成功/失败回调。

答案 1 :(得分:3)

一个类需要保留自己的想法表明可能存在设计问题。当一个物体保留自己时,不清楚谁拥有它或谁可能参考它,并且泄漏的风险很高。

什么班级负责提出segue?是否包含按钮的同一类?该类应保留segue,呈现segue,然后在/如果segue完成时释放segue。

如果不进一步了解视图控制器层次结构,很难给出具体的建议。但我的第一反应是建议决定是否提出segue的视图控制器应该在segue上具有强大的属性。子类化的segue可以定义一个协议,该提议类可以遵循该协议,以确定何时应该填充/释放segue。

答案 2 :(得分:1)

只需在self的数据成员数组中添加和删除self,如下所示:

@interface MyClass
{
    NSMutableArray* _selfRetains;
}
@end

@implementation MyClass
-(id)retainSelf
{ 
    [_selfRetains addObject:self];
    return self;
}
-(void)releaseSelf
{
    [_selfRetains removeLastObject];
}
@end

然后,将[self retain]替换为[self retainSelf],将[self release]替换为[self releaseSelf]

虽然其他答案都是正确的,并且您通常应该避免需要类保留自己的设计,但此解决方法并不要求您显着更改应用程序的设计。

答案 3 :(得分:-2)

如果您需要在异步操作中保留自我实例,可能是您的选择。