保留IBOutlet视图元素的最佳实践是什么?

5
我经常遇到包含大量IBOutlets的UIViewControllers,这些IBOutlets将控制器连接到其视图的子视图(通常是UILabels)。
按照“最佳实践”,即对所有UI元素使用保留:@property(retain,nonatomic)UILabel *theElement1@property(retain,nonatomic)UILabel *theElement2,...会在视图控制器的deallocviewDidUnload中产生大量的样板代码。
除了在加载nib时自动使用之外,不会在UIViewController之外使用或设置有问题的IBOutlets(set方法仅在viewDidUnload和nib加载时使用)。
“最佳实践”的结果是:
  • dealloc充斥着[theElement1 release][theElement2 release]等。
  • viewDidUnload中有[self setTheElement1:nil][self setTheElement2:nil]等。
然而,由于所有这些元素都已知被视图保留,并且视图在适当的时间由UIViewController释放,因此我认为没有任何理由让我手动管理它们。
这个特定的“最佳实践”的原因(据我所知)是要与您的保留一致。但是,一旦您开始拥有大量outlet,您更有可能在两种方法中的某个地方错过处理某些outlet,而不是正确更改outlet以保留那些您真正想要在视图消失后保留的特殊outlet。
除了我所知道的原因之外,是否存在其他原因需要遵循这个“最佳实践”,或者在子视图到UIViewController的视图的特定情况下,我应该完全自由打破这个“规则”?

我喜欢这个问题的主题。"真的" - VoodooChild
1个回答

4

你应该坚持这个最佳实践。当你在内存警告后访问IBOutlets时,它可以保护你免受非常奇怪的崩溃影响。是的,你需要手动管理你的IBOutlets。Accessorizer 可以很好地自动化这段代码。

在ObjC 2.0之前,我们也必须手写所有的访问器(@property和@synthesize是语言中非常新的添加)。事情已经变得更加美好了。随着我们向64位ABI和垃圾回收的转变,事情变得更加简单(你应该期望这些东西最终会进入iPhone)。

但现在,请遵循在Nib对象的内存管理中所规定的内存管理规则。你只需输入极少量的内容,却可以获得巨大的调试收益。(嗯,看起来他们又更新了这个文档;是时候自己学习一下了。)


很好——我之前还没看过那个Nib内存管理文档。 - Nathan S.
在一段时间后,我的另一个明智选择是手动生成 UI 元素并将它们放入 NSArray 中。但那就像举旗投降一样。拥有大约 20-30 个 IBOutlets 是维护的噩梦。那我为什么需要这么多 outlet 呢?我的答案是本地化 UILabels。 - Nuoji
除了使涉及这些字段的错误调试更加困难之外,还有什么缺点?实际上,对于这些特定字段,您可以放弃整个@property/@synthesize,并将这些字段设置为@private,以防止其他类错误地认为它们可以在视图删除时使用。我是在非常具体的UIViewControllers和(只读)子视图上下文中谈论。大量IBOutlets的问题似乎不太可能出现在其他情况下。 - Nuoji
如果你有20-30个标签,我建议只本地化NIB而不是标签。问题不是其他人搞乱你的outlets,而是视图控制器在标签被释放后修改outlet(以安装正确的标签)。每次由于内存警告重新加载时,你都需要重新连接这些标签。如果你不非常小心,当IBOutlet指针被释放时,你会修改它并导致崩溃。当我说“调试困难”时,我指的是“在内存紧张且不知道原因的情况下,在现场发生崩溃”。 - Rob Napier
重点是你会得到大量的样板代码。有了新的ABI,情况会好一些,因为你不需要到处合成。不幸的是,当你不合成时,在dealloc中需要做(有些棘手的)[self setTheOutlet:nil](虽然这可以显示出你没有正确地移除观察者...)优点是,有了新的ABI和不合成,dealloc和viewDidUnload行几乎相同,这缓解了一些痛苦。此外,不需要合成所有内容还可以消除另一个样板代码。 - Nuoji
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接