Mat*_*hen 5 iphone cocoa-touch objective-c
许多iPhone代码示例(来自Apple等)包含如下代码:
- (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];
}
Run Code Online (Sandbox Code Playgroud)
此片段来自BubbleLevel示例项目.
我的问题:为什么发布消息发送到contentView?我们在self.view中保留对contentView的引用,我们显然希望在应用程序的生命周期中使用它,而不仅仅是在此方法中.不会调用release会导致视图被释放吗?
Dav*_*ong 13
Ölbaum说是self.view = contentView;保留你的观点是正确的,这意味着它不会被解除分配.但是,这种行为并非总是如此:
如果您查看UIViewController的文档(或标题),您将看到该view属性声明如下:
@property(nonatomic, retain) UIView *view;
Run Code Online (Sandbox Code Playgroud)
这意味着无论何时设置(foo.view = anotherView或[foo setView:anotherView];)视图属性,都将保留另一个视图.如果view财产被宣布为:
@property(nonatomic, assign) UIView *view;
Run Code Online (Sandbox Code Playgroud)
然后视图将不会保留.它会将一个简单的指针指定到实例变量中.在这种情况下,你会是正确的,随后release到contentView会破坏认为,这意味着控制器将有一个陈旧的指针,这意味着您的应用程序可能会崩溃.
换句话说,当您使用属性时,请确保您知道它们是否是retain或assign.(如果没有说,那就是assign).然后相应地处理您的内存管理.
不要认为retain/ release只是为了平衡.他们所做的是转让所有权.理解所有权的概念,并了解Cocoa中的内存管理.
所有权在范围内设定; 方法范围,对象实例范围或全局应用程序范围.方法拥有保留局部变量.对象实例拥有一个保留的实例变量.应用程序拥有一个保留的全局变量.
如果您从名为的方法调用接收到该对象alloc,或者包含单词new或copy (As in newSprocket或mutableCopy),则当前方法拥有该对象.通过其他方式提供给您的所有对象都不归您所有,例如方法的参数或大多数方法调用的结果.
您可以访问您不拥有的对象实例,您可以一直这样做.retain如果您希望对象实例超过当前方法的执行(或者如果您想要挑剔的话,则运行循环),您只需要显式获取所有权.
这行代码取得了从局部变量引用的对象实例的所有权contentView.该方法loadView现在拥有该对象.
UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame];
Run Code Online (Sandbox Code Playgroud)
接下来,对象实例self获取所有权,因为该属性被声明为保留.对象实例现在有两个所有者,包括方法和类.
self.view = contentView;
Run Code Online (Sandbox Code Playgroud)
从这里开始,我们永远不会通过此方法中的局部变量访问视图对象.该方法不再需要它,因此重新拥有它.现在,该对象仅由对象实例拥有,并且不再是此方法的问题.
[contentView release];
Run Code Online (Sandbox Code Playgroud)
如果你已经习惯了其他语言,可能很自然地会看到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];
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,在设置属性时会保留它.所以你必须在那里发布它,否则分配对象造成的初始所有权永远不会被释放.