在大多数示例中,我看到了以下IBOutlets设置:
(Example A)
FooController.h:
@interface FooController : UIViewController {
UILabel *fooLabel;
}
@property (nonatomic, retain) IBOutlet UILabel *fooLabel;
@end
FooController.m:
@implementation FooController
@synthesize fooLabel;
@end
但这也很好用(注意:没有属性和合成):
(Example B)
FooController.h:
@interface FooController : UIViewController {
IBOutlet UILabel *fooLabel;
}
@end
FooController.m:
@implementation FooController
@end
在示例B中定义IBOutlets有什么缺点吗?比如内存泄露?似乎工作得很好,我不喜欢将IBOutlets公开为公共属性,因为它们不是这样使用的,它们只在控制器实现中使用。在没有真正需要的情况下,在三个地方定义它并不会让我觉得很枯燥(不要重复自己的话)。
发布于 2009-12-20 04:03:09
在Mac上,默认情况下不保留IBOutlets。这与iPhone OS上的行为相反:在iPhone OS上,如果不声明属性,则会保留该属性,并且必须在dealloc
方法中释放该属性。此外,64位运行时可以使用属性声明来合成实例变量。这意味着有一天实例变量(使用IBOutlet
)可能会被省略。
由于这些原因,创建总是一个属性并且只在该属性中使用IBOutlet
更加同构和兼容。不幸的是,它也更冗长。
在您的第一个示例中,您总是必须在dealloc
方法中释放插座。在第二个示例中,您必须仅在iPhone OS中释放插座。
发布于 2013-04-10 06:12:12
这些示例可能使用了保留,因为示例代码以编程方式分配和初始化UILabel,然后将其添加到UIView中。这是许多示例的情况,因为学习如何使用Interface Builder通常不是它们的重点。
第二个示例(无属性和无合成)是在开发人员在Interface Builder中“分配”UILabel (按钮、视图等)时使用的,方法是将IBOulet拖到标签或其他视图组件中。在我看来,前面的拖放操作(标签放到视图上)也会添加子视图、标签到视图--等等。标签由视图保留;视图由窗口保留;窗口由文件所有者保留。文件的所有者通常是在main中启动的文档。
您将注意到,当您单步执行程序时(通过添加awakeFromNib
- (void)awakeFromNib
{
[fooLabel blahblah];
}
该fooLabel已经有了一个内存地址。
这是因为标签是使用initWithCoder而不是init从文件包( nib文件)初始化的。它本质上是将文件流反序列化为一个对象--然后设置IBOutlet变量。(我们仍然在谈论IBOutlet方法)。
还要注意,前面提到的iOS方法使用键值方法
call [object setValue:outletValue forKey:@"<OutletName>"]
这就是观察者/观察者模式。该模式要求可观察对象引用Set/Array中的每个观察者。值的更改将迭代Set/Array并相等地更新所有观察者。该集合将已经保留每个观察者,因此在iOS中缺少保留。
进一步说,剩下的都是猜测。
似乎当你使用Interface Builder的时候,
@property (nonatomic, retain) IBOutlet UILabel *fooLabel;
应该可能更改为
@property (nonatomic, weak) IBOutlet UILabel *fooLabel;
或者@property (非原子,赋值) IBOutlet UILabel *fooLabel;
这样就不需要在dealloc方法中释放它了。另外,它将满足OSX和iOS的要求。
这是基于逻辑的,我可能在这里遗漏了一些部分。
然而,如果视图在程序的整个生命周期中都是持久的,这可能并不重要。而模式对话框中的标签(打开、关闭、打开、关闭)实际上可能在每个循环中具有过度保留和泄漏。这是因为(再次推测)每个关闭的对话框都被序列化到一个文件系统中,从而保持x,y位置和大小,以及它的子视图等,并随后反序列化...在下一次会话中打开(而不是说最小化或隐藏)。
https://stackoverflow.com/questions/1221516
复制相似问题