繁体   English   中英

保留IBOutlets的数量

[英]Retain counts of IBOutlets

在编码时,总是出现关于IBOutlets保留计数的相同问题:从NIB取消归档对象后保留计数? 何时将@property用于IBOutlet? 设置时保留还是分配? Mac和iPhone之间的区别?

因此,我阅读了Apple文档中的《笔尖对象生命周期》 Mac和iPhone上的一些测试应用程序给了我一些奇怪的结果。 尽管如此,我还是写下了一些规则来处理该问题,以便在编码时保持快乐,但现在我想与社区进行核实并听取您的意见和经验:

  1. 始终为顶级对象创建IBOutlet。 必要时用于非顶级对象(需要访问)。
  2. 始终为IBOutlets提供以下属性(并在必要时释放它们!):
    • Mac上的顶级对象:
      • @属性(非原子的, 分配 )IBOutlet SomeObject * someObject;
      • @synthesize someObject;
      • [self.someObject 版本 ];
    • Mac( 非发行版 )上的非顶级对象:
      • @属性(非原子, 分配 )IBOutlet NSWindow *窗口;
      • @synthesize someObject;
    • iPhone上的顶级对象(必须保留):
      • @属性(非原子性, 保留 )IBOutlet SomeObject * someObject;
      • @synthesize someObject;
      • [self.someObject 版本 ];
    • iPhone上的非顶级对象(应保留 ):
      • @属性(非原子的,保留)IBOutlet UIWindow *窗口;
      • @synthesize窗口;
      • [self.window 发布 ];

旁注:

  • 在Mac和iPhone上,插座通过设置器建立(如果有)。
  • 顶级对象:“没有所有者对象”
  • 非顶级对象:“具有父对象或所有者对象的任何对象,例如嵌套在视图层次结构中的视图。”

因此,问题将是: 这是正确且良好的做法吗?

希望您可以批准或更正。

始终让笔尖的文件所有者是NSWindowController或NSViewController(在Mac OS X上)或UIViewController(在iPhone上)的子类,并对其所有出口使用@property (retain) IBOutlet ,在控制器子类-dealloc进行适当的释放方法。

这种模式在Mac OS X iPhone OS上可以正常工作,因为Mac OS X上的NSWindowController和NSViewController为您隐式拥有顶级对象的所有权(并在其自己的-dealloc方法中放弃了),而iPhone OS则没有在笔尖加载期间为您获取顶级对象的任何隐式所有权。

顶级对象:“没有所有者对象”

尼克斯 顶级对象归文件所有者(文件的所有者)所有,因为它拥有文件中的所有顶级对象。

Windows可以方便地释放它们,但是我发现我可以关闭设计并自己管理其寿命(就像我拥有的​​任何其他对象一样),或者使用一个窗口,从而使我的设计更简洁(即使还有更多工作要做)。控制器。

如果您认为这与您引用的文档冲突,那么让我们遍历整个段落:

nib文件中的对象最初创建时的保留计数为1。但是,在重建对象层次结构时,AppKit会自动释放具有父对象或拥有对象的任何对象,例如嵌套在视图层次结构内部的视图。

从而杀死自己的所有权。 笔尖加载器不想拥有您的对象。

在完成nib加载代码时,只有nib文件中的顶级对象具有正的保留计数,并且没有拥有的对象。 您的代码负责释放这些顶级对象。

换句话说,它将所有权移交给您。

奇怪的是,如果对象的属性保留语义,则实际上会泄漏该对象。 文档说您应该保留它:

对于Mac OS X和UIKit,建议的管理nib文件中顶级对象的方法是在文件的Owner对象中为它们创建出口,然后定义setter方法以根据需要保留和释放这些对象。

但是,如果执行此操作,则即使释放对象所有权,该对象仍将保持活动状态。

我想我会为此提交一个错误。 (编辑:完成。x-radar:// problem / 7559755)至少,笔尖加载程序不应交出两个保留,这在我的测试应用程序中 (在10.5.8和10.6.1上)。

来自上面提到的苹果文档

对于Mac OS X和UIKit,建议的管理nib文件中顶级对象的方法是在文件的Owner对象中为它们创建出口,然后定义setter方法以根据需要保留和释放这些对象。 即使在应用程序使用垃圾回收的情况下,Setter方法也为您提供了一个适当的位置来包含您的内存管理代码。 一种简单的实现setter方法的方法是创建一个声明的属性(使用@property语法),然后让编译器为您创建它们。 有关如何定义属性的更多信息,请参见Objective-C编程语言。

否则,使用@property(非原子的,保留)IBOutlet * outletName;

我可以对iPhone NIB开发发表自己的看法:

  • 如果使用IB,则使用尽可能多的IBOutlet(有时在构建NIB时您不知道视图层次结构-它可能是动态的)或根本不使用它们-否则会一团糟
  • 仅当您要从视图控制器外部访问视图时(如果它们应该是公共的),才使用属性
  • AFAIK无需管理IBOutlets的内存

希望能帮助到你...

您应该遵循标准的内存管理准则。 如果您的插座已连接到retain属性,则必须在-dealloc消息中释放它。

是的,您通常需要自己保留任何其他对象未保留的顶级对象。

1)总的来说,为什么会有一个没有IBOutlet指向的顶级对象? 这项要求从未看起来非常严格。

2)我认为您已经为iPhone设置了正确的设置。 您也可以在iPhone上使用assign属性,这可以达到您的期望...但是通常,在大量使用后,我更喜欢使用keep属性,因此当我考虑释放对象时,我100%清楚(特别是要使用viewDidUnload方法来实现)。

另外,仅作为旁注,调用[self.property release]不是一种好形式。 如果其他方法也释放了该对象,则该引用将保持完整,但可能是无效的……要么说self.property = nil,要么(更好)直接将基础类变量设置为nil,而无需在dealloc语句中使用属性(以避免任何在dealloc中可能产生的副作用)。

就像我在另一个海报中提到的那样,您可以使用在私有类-本地类别扩展中声明的IBOutlet属性来保持环境整洁,因此它们不是公共属性。 看起来像:

// in .m file
@interface MyClass ()
@property (nonatomic, retain) IBOutlet UIView *myPrivateView;
@end

@implementation MyClass
@synthesize myPrivateView;
.....

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM