当方法仍在运行时,Dealloc被调用

时间:2012-06-20 20:29:53

标签: objective-c ios synchronized

在我正在研究的项目中(我选择了这段代码并且我一直在尝试调试它),我有一个由观察者调用的函数。观察者调用一种方法来更新要放在屏幕上的数据。当更新发生时(更新发生需要几秒钟),用户可以按导航栏上的“返回”按钮,这会导致发生dealloc调用。当该方法运行时,dealloc调用释放所有ivars,当方法尝试访问ivars时,最终会导致EXC_BAD_ACCESS。更新方法的结构也附有@synchronized块。

- (void)update {

@synchronized(self){
  // some code here...
  // Also access ivars here.
  }

}

在解除分配之前,可以做些什么来告诉控制器先完成方法?我已经尝试在dealloc中运行带有条件的while循环,但这看起来效率不高。如果控制器被释放,它也永远不会完全执行,并且处于死锁状态。我觉得解决方案很简单,但是我的大脑在工作中度过了漫长的一天,我无法想到它。

4 个答案:

答案 0 :(得分:2)

您可以在retain上致电self,以确保在运行较长时间的方法时引用计数不会达到零;并以这种方式避免dealloc:

- (void) update {
    [self retain]

    // do work ...

    [self release]
 }

答案 1 :(得分:1)

如果你把你需要做的工作放在一个块中,编译器将自动保留块内引用的所有对象(包括self)。例如:

- (void)update {
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // some code here, access ivars, do whatever you want
    }];
}

更新方法将立即返回,并且该块将被安排在主运行循环上运行(此处不涉及辅助线程)。

如果更新工作是一个长时间运行的任务,您可以使用后台队列而不是主队列,然后(在该块内)安排另一个块在主队列上运行并在工作时与UI交互完了。

答案 2 :(得分:0)

由于你在谈论NavigationBar,我的猜测是发生的事情是你的NavigationController发布了对你的UIViewController类的引用,而UIViewController类又持有了ivars。绕过它的一种方法是将对象保留在viewcontroller中,直到进行计算,正如其他答案所示。但是,如果您正在进行的计算是为了计算该视图中应显示的数据,则下次打开同一视图时,您将从头开始重新加载视图。

我要做的是,我将保留对您在navigationcontroller之外使用的ViewController的引用,以便在用户按下后退按钮时不会释放它。

然后,如果用户回到同一视图,您将已经加载了数据。只需使用相同的参考再次推动它。

示例:

@interface YourRootViewController : UIViewController {
    YourNextControllerClass *nextController;
}

@property (nonatomic, retain) YourNextControllerClass *nextController;

@end

在顶级ViewController的ViewDidLoad中:

self.nextController = [[[YourNextControllerClass alloc] initWithNibName:@"YourNextControllerNib" bundle:nil] autorelease];

当您想要显示视图时:

[myNavigationController pushViewController:nextController animated:YES];

如果用户按下后退按钮,则不会释放视图控制器,因此当您再次按下它时,一切都会在您离开时出现。

答案 3 :(得分:0)

解决方案取决于您是否要将该对象保持活动状态到方法的末尾。但是,你也使用@synchronized(self):我会非常害怕如果self被解除分配并且@synchronized试图删除对self的锁定会发生什么,所以在这种情况下我会尝试让它保持活着状态。 (但是,@ synchronised然后运行大量代码在我看来并不是一个好主意; @synchronised应该用于尽可能少的代码以避免死锁)。

使用ARC,将对象保持在方法中是很简单的。

typeof (self) myself = self; 

将为自己创造一个强有力的参考。最好在方法体中使用自己而不是自己。

如果你不想保持对象“自我”活着,那就是通常的情况:

__weak typeof (self) weakSelf = self; 

然后,无论你想确定自己还在哪里,你都要写

typeof (self) strongSelf = weakSelf;
if (strongSelf != nil) {
}