Objective c 为什么iPhone示例代码使用了这么多中间变量?
我目前正在进行Apress的“开始iPhone3开发”。他们在示例应用程序中使用的标准如下所示:Objective c 为什么iPhone示例代码使用了这么多中间变量?,objective-c,ios,memory-management,simplification,Objective C,Ios,Memory Management,Simplification,我目前正在进行Apress的“开始iPhone3开发”。他们在示例应用程序中使用的标准如下所示: - (void)viewDidLoad { BlueViewController *blueController = [[BlueViewController alloc] initWithNibName:@"BlueView" bundle:nil]; self.blueViewController
- (void)viewDidLoad {
BlueViewController *blueController = [[BlueViewController alloc]
initWithNibName:@"BlueView" bundle:nil];
self.blueViewController = blueController;
[self.view insertSubview:blueController.view atIndex:0];
[blueController release];
}
8.14.11更新(附加信息)blueViewController声明如下:
@property (retain, nonatomic) BlueViewController *blueViewController;
- (void)viewDidLoad {
self.blueViewController = [[BlueViewController alloc]
initWithNibName:@"BlueView" bundle:nil];
[self.view insertSubview:blueViewController.view atIndex:0];
}
- (void)dealloc {
[blueViewController release];
[super dealloc];
}
每当他们执行一个alloc
时,他们就把它放在某个临时变量中(这里是blueController
),然后分配它,然后释放它。这个温度变量对我来说似乎是多余的。我将代码简化如下:
@property (retain, nonatomic) BlueViewController *blueViewController;
- (void)viewDidLoad {
self.blueViewController = [[BlueViewController alloc]
initWithNibName:@"BlueView" bundle:nil];
[self.view insertSubview:blueViewController.view atIndex:0];
}
- (void)dealloc {
[blueViewController release];
[super dealloc];
}
我修改过的代码在iPhone模拟器中运行时也一样。
现在,我知道了一条规则,如果你分配了一些东西,你需要释放它。我在我的dealoc
方法中介绍了这一点。但是直接在viewdiload
中发布有什么好处吗(调用alloc
的函数)?或者在您的dealoc
方法中使用release
也同样可以吗?谢谢你的帮助,
-j有两个原因我可以从脑海里想出来;第一个更具体的例子是,您经常会看到类似的方法,其中
blueController
被分配和初始化,然后在实际分配给self
的ivar之前进行有效性测试。如果您意识到需要这样做,那么在每种这样的方法中遵循这种模式将使您更容易在创建对象和分配对象之间进行测试。据我所知,如果这样的中介确实是多余的,编译器应该优化它
Cocoa中这种模式的第二个更一般的用途是,Obj-C和Cocoa鼓励方法和变量使用非常长、详细的名称,因此单个方法调用可能最终跨越多行;使用方法调用作为其他方法的直接参数可能很快变得不可读,因此约定鼓励提前为方法设置每个参数,将它们放置在中间变量中,然后将变量用作参数以增强可读性,并且可以更轻松地更改单个参数,而无需深入研究嵌套的方法调用。假设
blueViewController
是retain
属性,那么临时变量并不是多余的。您的简化正在创建内存泄漏。第二个代码段中的此语句泄漏:
self.blueViewController = [[BlueViewController alloc]
initWithNibName:@"BlueView" bundle:nil];
就所有权而言,您拥有alloc init返回的对象,然后属性访问器再次声明该对象的所有权,导致该对象被过度保留
使用临时变量可以解决此问题。另一个选项是使用autorelease
:
self.blueViewController = [[[BlueViewController alloc]
initWithNibName:@"BlueView" bundle:nil] autorelease];
请注意,在此语句之后,您实际上拥有该对象,并且必须在dealloc中释放它
您没有提到如何声明属性
blueViewController
。无论如何,不管setter的语义是什么(retain
,copy
,assign
),该语句都是错误的。我已经解释了最可能的情况:retain
。让我们看看另外两种可能性(不考虑它们是否有意义):
- 如果
恰好是blueViewController
属性,则语句也会泄漏。属性访问器复制原始对象,现在该属性持有指向该副本的指针,您失去了对原始对象的跟踪,并立即将其泄漏copy
- 最不可能出现的情况是
是blueViewController
属性,因为这很可能是错误的,并且您确实希望assign
。但是,无论如何,保留
属性用于您不拥有的对象,例如代理,您不应该释放它们。您正在将自己拥有的对象指定给它,因此要么泄漏该对象,要么错误地释放了assign属性assign
alloc
获得一次所有权。然后,在第二行中,当财产被保留时,您再次获得所有权。在第三行中,您将通过alloc
获得所有权。现在,您通过retain属性拥有一个所有权,您可能会在将来发布它,它可能位于dealloc
中
现在考虑如果删除<代码> TMPOBJ会发生什么。
self.obj = [[MyClass alloc] init];
在这一行中,您两次获得所有权,一次通过
alloc
获得,一次通过property获得。现在[obj release]
一次是不够的。您需要释放它两次以避免泄漏,自然地,释放两次是非常糟糕的,并且可能导致进一步的内存泄漏。如果您再次调用self.obj=anotherObj,则您正在泄漏旧的。为了避免这种情况,您需要这个临时指针 这是一个很好的观点,而且不像我的回答那样,它不仅仅是指风格上的观点。通常,如果您希望直接将新对象分配给ivar,则应使用自动释放便利方法。如果您必须使用名称中包含alloc、init、new或copy的方法,则必须将其分配给temp,然后将其释放。谢谢albertamg,这回答了我的问题。感谢您花时间解释。我在想发行版
可以涵盖无限量的alloc
s和retain
s。我认为这是一个重要的区别,release
所做的就是将对象的保留计数减少1.Taskinoor-谢谢你的回答。这无疑有助于我更好地理解objective c的内存管理。