在我正在研究的项目中(我选择了这段代码并且我一直在尝试调试它),我有一个由观察者调用的函数。观察者调用一种方法来更新要放在屏幕上的数据。当更新发生时(更新发生需要几秒钟),用户可以按导航栏上的“返回”按钮,这会导致发生dealloc调用。当该方法运行时,dealloc调用释放所有ivars,当方法尝试访问ivars时,最终会导致EXC_BAD_ACCESS。更新方法的结构也附有@synchronized
块。
- (void)update {
@synchronized(self){
// some code here...
// Also access ivars here.
}
}
在解除分配之前,可以做些什么来告诉控制器先完成方法?我已经尝试在dealloc中运行带有条件的while循环,但这看起来效率不高。如果控制器被释放,它也永远不会完全执行,并且处于死锁状态。我觉得解决方案很简单,但是我的大脑在工作中度过了漫长的一天,我无法想到它。
答案 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) {
}