在我的应用程序工作流程中的不同时刻,我需要显示一个视图。该视图非常耗费内存,因此我希望在用户丢弃它时将其解除分配。所以,我写了下面的代码:
- (MyView *)myView {
if (myView != nil)
return myView;
myView = [[UIView alloc] initWithFrame:CGRectZero]; // allocate memory if necessary.
// further init here
return myView;
}
- (void)discardView {
[myView discard]; // the discard methods puts the view offscreen.
[myView release]; // free memory!
}
- (void)showView {
view = [self myView];
// more code that puts the view onscreen.
}
不幸的是,这种方法只能在第一次使用。将视图置于屏幕上的后续请求会导致"message sent to deallocated instance"
错误。显然,解除分配的实例与nil不同。我想在[myView release]
之后添加一行myView = nil
。但是,这可能会导致错误(在该行之后调用myView
可能会产生错误)。
那么,我该如何解决这个问题?
答案 0 :(得分:4)
将myView
设置为nil
是正确的做法。 不这样做是产生错误的原因,因为它不可察觉地引用了一个解除分配的对象。您的代码测试nil
以查看是否需要创建新视图,因此您应该适当地设置变量。
答案 1 :(得分:1)
因为你没有使用访问器,你会遇到问题。您需要为视图定义属性。然后,每当您引用视图时,请使用自点符号。如果你这样做,那么只需将view属性设置为nil,如下所示:
self.myView=nil;
...将自动触发其释放。
但是,这是管理视图的不好方法,尤其是从nib加载视图时。视图很可能是控制器对象的必需属性。将其设置为nil会引发崩溃。
更好的方法是让视图控制器处理内存问题。在iPhone上,您可以将内存管理代码放在viewDidDisappear:
或didReceiveMemoryWarning
中。在任何情况下,只要控制器处于活动状态,您就不会终止视图,而是释放视图的内存密集部分,例如图片。这使视图成为轻量级shell对象。然后在'viewWillAppear`中重新加载内存密集型部分。
但是,处理此问题的最佳方法是从导航堆栈中实际弹出视图控制器。此时视图控制器会自动清理。