保留IBOutlets的数量

时间:2010-01-19 22:51:58

标签: iphone objective-c cocoa macos nib

虽然编码始终存在与IBOutlets的保留计数相同的问题:在从NIB取消归档对象后保留计数?何时使用@ property's作为IBOutlet?设置时保留或分配? Mac和iPhone之间的差异?

所以我从Apple的文档中读到了The Nib Object Life Cycle。 Mac和iPhone上的一些测试应用程序给了我一些奇怪的结果。不过我写了一些规则如何处理这个问题,以便在编码时保持快乐,但现在想要与社区核实并倾听您的​​意见和经验:

  1. 始终为顶级对象创建IBOutlet。对于非顶级对象(如果需要)(需要访问)。
  2. 始终为IBOutlets提供如下属性(并在必要时释放它们):
    • Mac上的顶级对象:
      • @property(非原子,赋值)IBOutlet SomeObject * someObject;
      • @synthesize someObject;
      • [self.someObject 发布];
    • Mac上的非顶级对象(无发布):
      • @property(非原子,指定)IBOutlet NSWindow *窗口;
      • @synthesize someObject;
    • iPhone上的顶级对象(必须保留):
      • @property(非原子,保留)IBOutlet SomeObject * someObject;
      • @synthesize someObject;
      • [self.someObject 发布];
    • iPhone上的非顶级对象(应保留):
      • @property(nonatomic,retain)IBOutlet UIWindow * window;
      • @synthesize window;
      • [self.window 发布];
  3. 附注:

    • 在Mac和iPhone上,如果可用,则使用设置器连接。
    • 顶级对象:“没有拥有对象”
    • 非顶级对象:“具有父对象或拥有对象的任何对象,例如嵌套在视图层次结构中的视图。”

    所以问题是:这是正确和良好的做法吗?

    我希望你能批准或纠正它。

6 个答案:

答案 0 :(得分:10)

始终让你的笔尖'文件的所有者成为NSWindowController或NSViewController(在Mac OS X上)或UIViewController(在iPhone上)的子类,并使用@property (retain) IBOutlet作为其所有出口,在控制器子类-dealloc方法中执行适当的发布。

此模式适用于两者 Mac OS X iPhone OS,因为Mac OS X上的NSWindowController和NSViewController会为您隐藏所有顶层对象(并在他们自己的-dealloc方法中放弃它,并且在操作nib加载期间,iPhone OS不会为您提供任何隐含的顶级对象所有权。

答案 1 :(得分:1)

  

顶级对象:“没有拥有对象”

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

Windows有这个选项来释放自己是为了方便,但我发现我的设计更干净(即使它更多一些工作)当我关闭它并自己管理它的生命周期,就像我拥有的​​任何其他对象,或者使用窗口控制器。

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

  

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

从而扼杀了自己的所有权。 nib加载器不想拥有你的对象。

  

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

换句话说,它正在将所有权交给你。

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

  

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

但是如果你这样做,即使你释放了它的所有权,该对象仍将保持活着。

我想我会提出一个关于此问题的错误。 (编辑:完成.x-radar:// problem / 7559755)至少,nib加载器不应该切换两个保留,它在my test app(在10.5.8和10.6.1)。

答案 2 :(得分:1)

从上面提到的apple's doc

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

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

答案 3 :(得分:0)

我可以写下我对iPhone NIB开发的看法:

  • 如果您使用IB,那么尽可能多地使用IBOutlet(有时您在构建NIB时不知道视图层次结构 - 它可能是动态的)或根本不使用它们 - 否则会出现混乱
  • 仅当您要从View Controller外部访问视图时(如果它们应该是公共的)
  • ,才使用属性
  • AFAIK没有必要为IBOutlets管理内存

希望它有所帮助...

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

1)一般来说,为什么你会有一个没有IBOutlet的顶级对象指向它呢?这个要求从来没有像现在这样严格限制。

2)我认为你有适合iPhone的设置。你也可以在iPhone上使用assign属性,这可以达到你所期望的......但是通常在经过大量使用后我更喜欢使用retain属性,因此当我考虑释放对象时,我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;
.....