Iphone IBOutlet是否需要是一个属性&;合成的?
在大多数示例中,我看到以下IBOutlets设置:Iphone IBOutlet是否需要是一个属性&;合成的?,iphone,interface-builder,Iphone,Interface Builder,在大多数示例中,我看到以下IBOutlets设置: (Example A) FooController.h: @interface FooController : UIViewController { UILabel *fooLabel; } @property (nonatomic, retain) IBOutlet UILabel *fooLabel; @end FooController.m: @implementation FooController @synt
(Example A)
FooController.h:
@interface FooController : UIViewController {
UILabel *fooLabel;
}
@property (nonatomic, retain) IBOutlet UILabel *fooLabel;
@end
FooController.m:
@implementation FooController
@synthesize fooLabel;
@end
但这也很好(注意:没有属性也没有合成):
如例B所示定义IBOutlets有什么缺点吗?比如内存泄漏?似乎工作得很好,我不想将IBOutlets公开为公共属性,因为它们不是这样使用的,它们只在控制器实现中使用。在没有实际需要的情况下,在三个地方定义它不会让我觉得很枯燥(不要重复你自己)。最终结果完全相同,但你必须记住以下几点:
- 将实例字段用作出口时,不应在dealoc中释放它们
- 使用具有(retain)属性的属性时,必须在dealloc中释放属性(使用
或通过释放支持变量)。这使得事情变得更加透明self.property=nil
实际上,这一切都归结为同一条老规则:“你应该释放你分配/保留的东西”。因此,如果您使用实例字段作为出口,您没有分配/保留它,因此不应该释放它。在Mac OS X上,IBOutlets的连接方式如下:
在Mac OS X上,默认情况下不会保留IBoutlet。这与iPhone操作系统上的行为相反:在iPhone操作系统上,如果不声明属性,它将被保留,并且必须在
dealoc
方法中释放此属性。此外,64位运行时可以使用属性声明合成实例变量。这意味着有一天实例变量(带有IBOutlet
)可能会被省略
由于这些原因,始终创建一个属性并仅在属性中使用IBOutlet
更为一致和兼容。不幸的是,它也更加冗长
在第一个示例中,您必须始终使用
dealloc
方法释放插座。在第二个示例中,您必须仅使用iPhone操作系统释放插座。这些示例可能使用retain,因为示例代码以编程方式分配和初始化UILabel,然后将其添加到UIView。很多例子都是这样,因为学习如何使用Interface Builder通常不是他们的重点
第二个例子(无属性和无合成)是在开发人员在界面生成器中“分配”UILabel(按钮、视图等)时使用的,方法是将IBOulet拖到标签或其他视图组件上。在我看来,前面的拖放操作(标签放到视图上)也会添加子视图、标签到视图,依此类推。标签由视图保留;窗口保留一个视图;窗口由文件的所有者保留。文件的所有者通常是在main中启动的文档
您将注意到,当您单步执行程序时(通过添加awakeFromNib)
- (void)awakeFromNib
{
[fooLabel blahblah];
}
那个傻瓜已经有一个内存地址了
这是因为标签是从文件包(nib文件)初始化的,使用的不是init而是initWithCoder。它本质上是将文件流反序列化为一个对象,然后设置IBOutlet变量(我们仍然在讨论IBOutlet方法)
还要注意,前面提到的iOS方法使用Key-Value方法
call [object setValue:outletValue forKey:@"<OutletName>"]
可能应该改为
@property (nonatomic, weak) IBOutlet UILabel *fooLabel;
或
@属性(非原子,赋值)IBUILabel*傻瓜标签
然后它就不需要以dealloc的方式发布,而且它还可以满足OSX和iOS的要求
这是基于逻辑,我可能会遗漏一些东西
尽管如此,视图是否在程序的整个生命周期内保持不变可能并不重要。然而,模式对话框中的标签(打开、关闭、打开、关闭)实际上可能会在每个周期内过度保留和泄漏。这是因为(再次推测)每个关闭的对话框都被序列化到文件系统中,从而保持x、y位置和大小以及其子视图等,然后在下一个打开的会话中反序列化(而不是说最小化或隐藏)。此建议适用于Mac OS x,但不适用于iPhone OS。请参阅下面的答案。调用“self.property=nil”在dealloc方法中,这不是一个很好的实践。您不应该从init或dealloc调用方法,如果您是子类化的,那么您的子类可能不希望这些setter在解除锁定之后或初始化之前被调用。这是释放使用实例变量合成的自动保留属性的唯一方法(无任何支持字段的明确声明)。您没有选择,不管是好的做法还是不好的做法。如果您没有使用垃圾收集,请声明一个备份实例变量。这就是要点:使用实例变量合成时没有备份实例变量。因此,如果您选择使用自动实例变量合成,则释放它的唯一方法是通过设置把房子归零。嗨,乔恩,谢谢你详细的回答
@property (nonatomic, retain) IBOutlet UILabel *fooLabel;
@property (nonatomic, weak) IBOutlet UILabel *fooLabel;