2009-09-06 19 views
5

许多iPhone代码样本(来自苹果等)后,立即释放包括这样的代码:目标C:为什么创建UI对象

- (void)viewDidLoad { 
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; 

// add the top-most parent view 
UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame]; 
contentView.backgroundColor = [UIColor blackColor]; 
self.view = contentView; 
[contentView release]; 

levelView = [[LevelView alloc] initWithFrame:applicationFrame viewController:self]; 
[self.view addSubview:levelView]; 

calibrationView = [[CalibrationView alloc] initWithFrame:applicationFrame viewController:self]; 
} 

这个片段是从BubbleLevel样本项目。

我的问题:为什么发送消息发送到contentView?我们在self.view中保留对contentView的引用,我们显然希望在应用程序的整个生命周期中使用它,而不仅仅是这种方法。不会调用release会导致视图被释放?

+0

谢谢大家的解释。 – 2009-09-07 15:31:56

回答

6

不要以为retain/release简单,如被一些平衡。他们所做的是转移所有权。了解所有权的概念,并了解Cocoa中的内存管理。

所有权在范围内设置;方法范围,对象实例范围或全局应用程序范围。通过保留局部变量,方法拥有。对象实例通过保留实例变量拥有。和应用由具有保留全局变量拥有。如果你从一个名为alloc一个方法调用收到了

目前的方法拥有对象,或包含单词新的或复制(如newSprocketmutableCopy。通过其他方式提供给您的所有对象不属于您,例如您的方法的参数或大多数方法调用的结果。

您可以访问你没有自己的对象的情况下,你做这一切的时间。你只需要,如果你想对象实例住过去的当前方法的执行明确把所有权与retain(或运行循环,如果你想成为挑剔的)

这行代码需要从局部变量contentView引用的对象实例的所有权。方法loadView现在拥有该对象。

UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame]; 

接下来是对象实例self取得所有权,因为该属性被声明为保留。对象实例现在有两个所有者,方法和类。

self.view = contentView; 

从这里开始,我们从来没有通过这个方法中的局部变量访问视图对象。该方法不再需要它,从而辞去它的所有权。现在,对象只由对象实例拥有的,而不再是这个方法的问题

[contentView release]; 
+0

很好的解释。 但是,我认为强调你应该释放实例是个好主意,因为你首先分配了它。不仅你不再需要它,而且在方法结束时,你将失去对本地变量的访问权限。 – 2009-09-07 15:43:25

8

不,因为self.view = contentView会保留它。由于您必须平衡保留和释放呼叫,您需要释放它以平衡分配。

5

如果你对使用其他语言,可能是自然看self.view = contentView,并认为,“噢,它分配一个实例变量。”但它不是 - 实例变量不能用点分配,因为Objective-C中的对象始终是指针。这是一个属性访问器。在大多数情况下,它完全等同于编写[self setView:contentView]

在大多数情况下,setter方法将实施这样的事情:

- (void)setView:(UIView *)view { 
    if (view != _view) { 
     [_view release]; // where _view is the name of the actual instance variable 
     _view = [view retain]; 
    } 
} 

在这样的情况下,当你设置的属性也被保留。所以你必须在那里释放它,否则分配对象引起的初始所有权永远不会被释放。

13

Ölbaum是说self.view = contentView;将保留您的观点,这意味着它不会被释放正确。但是,此行为不会永远是这样:

如果你在文档看看(或头)的UIViewController中,你会看到view属性声明如下:

@property(nonatomic, retain) UIView *view; 

这意味着无论何时设置视图属性(foo.view = anotherView[foo setView:anotherView];),其他视图都将保留。如果view财产申报为:

@property(nonatomic, assign) UIView *view; 

那么该视图保留。它会将一个简单的指针分配到实例变量中。在这种情况下,后续的releasecontentView会破坏视图,这意味着控制器会有一个陈旧的指针,这意味着您的应用可能会崩溃。

换句话说,当您使用属性时,请确保您知道他们是否是retainassign。 (如果它不说,那么它是assign)。然后相应地处理你的内存管理。