创建局部变量和分配给ivar并直接分配给ivar之间的区别?

时间:2010-02-05 22:30:57

标签: iphone variables instance variable-assignment local

我一直想知道为什么所有苹果代码示例都使用这样的代码:

UINavigationController *aNavigationController = [[UINavigationController alloc]
          initWithRootViewController:rootViewController];

self.navigationController = aNavigationController;

[self.view addSubview:[navigationController view]];

[aNavigationController release];

他们总是创建一个局部变量并将其分配给ivar为什么他们不这样做:

self.navigationController = [[UINavigationController alloc]
          initWithRootViewController:rootViewController];;

[self.view addSubview:[navigationController view]];

[navigationController release];

还有其他原因,除了它更容易理解吗?这是最佳做法吗?

-Oscar

5 个答案:

答案 0 :(得分:2)

您的替换代码不正确,从而说明了Apple试图阻止的问题。这是你的代码:

self.navigationController = [[UINavigationController alloc]
      initWithRootViewController:rootViewController];

[self.view addSubview:[navigationController view]];

[navigationController release];

你遗漏了“自我”。在你的参考文献中也许您打算直接访问ivar,但在这种情况下,您通过混合访问器和直接ivar访问(并通过在访问器外使用直接ivar访问违反了基本规则)创建了非常混乱的代码。如果没有,那么你打算写下这个:

self.navigationController = [[UINavigationController alloc]
      initWithRootViewController:rootViewController];

[self.view addSubview:[self.navigationController view]];

[self.navigationController release];

最后一行非常错误。永远不要发送--release到方法调用的结果。所以不,你这样做的方式不正确。

那就是说,Apple和我不同意如何做到这一点。我是这样做的:

self.navigationController = [[[UINavigationController alloc]
      initWithRootViewController:rootViewController] autorelease;

[self.view addSubview:[self.navigationController view]];

我喜欢-autorelease因为我发现它可以防止错误。分配和释放越远,开发人员注入内存泄漏的可能性越大(例如通过添加“返回”)。 autorelease通过将保留和释放保持在一起来避免这种情况,使得将其用作临时变量的意图更加清晰,并且通常使代码检查更容易。

Apple在他们的示例代码中倾向于不同意我,因为他们通过使用release与autorelease来强调性能。我发现这是一个错误的优化,因为在这个运行循环期间这个对象不会被释放(因此没有保存内存),我相信自动释放的非常小的性能损失超过了减少因错误使用释放导致的内存泄漏。

自动释放与发布争论充满了灰色阴影(我当然直接在循环中使用发布),不同的开发人员有不同的方法,但在任何一种情况下,替换代码都不是正确的方法。< / p>

答案 1 :(得分:1)

第一行的不同之处在于,Apple的版本将对象创建和赋值分离为ivar,而您的版本将两者放在一起。从概念上讲,Apple的版本稍微容易理解。据我所知,这不是最佳实践。

答案 2 :(得分:1)

两个版本都错过了检查零值:

(假设self.navigationController是一个保留其值的属性)

self.navigationController = [[UINavigationController alloc]
    initWithRootViewController:rootViewController];
if (self.navigationController != nil) {
    [self.view addSubview: navigationController.view;
    [self.navigationController release];
}

你可能会认为这是风格,但在我看来,它会减少错误的代码。

答案 3 :(得分:1)

它可能与顶部示例相同,但它有可能不会。

请记住

self.navigationController = aNavigationController;

相同
[self setNavigationController:aNavigationController];

并且您不知道setNavigationController方法内部发生了什么。它可能正在初始化一个不同的对象,并将其设置为iVar,然后释放,导致崩溃。

答案 4 :(得分:0)

因为很明显代码使用的是UINavigationController实例变量。然后没有理由这样做:

self.navigationController = aNavigationController

如果你不保留它。

但是,如果你这样做:

 self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];

之后,如果你这样发布它:

[navigationController release];

似乎我们正在释放应该在初始化导航控制器的当前类的生命周期中保留的实例变量。因此,它很容易出错,这会让初学者认为它只应该以dealloc方法发布。

两种方法最终都会保留0。如果在dealloc实现:

[navigationController release]; // 1 for the ivar
[super dealloc]; // 0 for the retained subviews