17

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

我有一个习惯UIStoryboardSegue,我使用 Facebook Connect(或其他服务)将用户登录到我的应用程序。简而言之,它应该执行以下操作:

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

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

我想到了一个快速'n'dirty hack来防止这种情况:

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

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

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

- (void) loginServiceDidSucceed:(BSLoginService *)svc {
    ...
    _retained_self = nil;
}

问题是,它确实一个 hack,所以我想知道是否还有其他更优雅的方式可以做到这一点?

4

4 回答 4

9

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

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

看起来您必须在UIStoryboardSegue某处存储对您的子类的引用才能调用loginServiceDidSucceed:它,所以也许只是制作一个强引用就可以了。再一次,从中引用它(例如登录成功时的完成块)是理想的。我建议调整您的登录代码以使用块进行成功/失败回调。

于 2012-05-10T13:49:34.217 回答
3

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

哪个类负责呈现 segue?它是包含按钮的同一个类吗?此类应保留转场,呈现转场,然后在转场完成时/如果转场完成则释放转场。

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

于 2012-05-10T16:01:53.920 回答
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]

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

于 2013-11-04T08:51:58.430 回答
-2

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

于 2014-09-12T02:48:10.847 回答