首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >IBOutlet是否需要是属性&合成的?

IBOutlet是否需要是属性&合成的?
EN

Stack Overflow用户
提问于 2009-08-03 10:00:04
回答 2查看 30K关注 0票数 53

在大多数示例中,我看到了以下IBOutlets设置:

代码语言:javascript
复制
(Example A)

FooController.h:

@interface FooController : UIViewController {
    UILabel *fooLabel;
}

@property (nonatomic, retain) IBOutlet UILabel *fooLabel;

@end

FooController.m:

@implementation FooController

@synthesize fooLabel;

@end

但这也很好用(注意:没有属性和合成):

代码语言:javascript
复制
(Example B)

FooController.h:

@interface FooController : UIViewController {
    IBOutlet UILabel *fooLabel;
}

@end

FooController.m:

@implementation FooController

@end

在示例B中定义IBOutlets有什么缺点吗?比如内存泄露?似乎工作得很好,我不喜欢将IBOutlets公开为公共属性,因为它们不是这样使用的,它们只在控制器实现中使用。在没有真正需要的情况下,在三个地方定义它并不会让我觉得很枯燥(不要重复自己的话)。

EN

回答 2

Stack Overflow用户

发布于 2009-12-20 04:03:09

在Mac上,默认情况下不保留IBOutlets。这与iPhone OS上的行为相反:在iPhone OS上,如果不声明属性,则会保留该属性,并且必须在dealloc方法中释放该属性。此外,64位运行时可以使用属性声明来合成实例变量。这意味着有一天实例变量(使用IBOutlet)可能会被省略。

由于这些原因,创建总是一个属性并且只在该属性中使用IBOutlet更加同构和兼容。不幸的是,它也更冗长。

在您的第一个示例中,您总是必须在dealloc方法中释放插座。在第二个示例中,您必须仅在iPhone OS中释放插座。

票数 12
EN

Stack Overflow用户

发布于 2013-04-10 06:12:12

这些示例可能使用了保留,因为示例代码以编程方式分配和初始化UILabel,然后将其添加到UIView中。这是许多示例的情况,因为学习如何使用Interface Builder通常不是它们的重点。

第二个示例(无属性和无合成)是在开发人员在Interface Builder中“分配”UILabel (按钮、视图等)时使用的,方法是将IBOulet拖到标签或其他视图组件中。在我看来,前面的拖放操作(标签放到视图上)也会添加子视图、标签到视图--等等。标签由视图保留;视图由窗口保留;窗口由文件所有者保留。文件的所有者通常是在main中启动的文档。

您将注意到,当您单步执行程序时(通过添加awakeFromNib

代码语言:javascript
复制
- (void)awakeFromNib
{
    [fooLabel blahblah];
}

该fooLabel已经有了一个内存地址。

这是因为标签是使用initWithCoder而不是init从文件包( nib文件)初始化的。它本质上是将文件流反序列化为一个对象--然后设置IBOutlet变量。(我们仍然在谈论IBOutlet方法)。

还要注意,前面提到的iOS方法使用键值方法

代码语言:javascript
复制
  call [object setValue:outletValue forKey:@"<OutletName>"]

这就是观察者/观察者模式。该模式要求可观察对象引用Set/Array中的每个观察者。值的更改将迭代Set/Array并相等地更新所有观察者。该集合将已经保留每个观察者,因此在iOS中缺少保留。

进一步说,剩下的都是猜测。

似乎当你使用Interface Builder的时候,

代码语言:javascript
复制
 @property (nonatomic, retain) IBOutlet UILabel *fooLabel;

应该可能更改为

代码语言:javascript
复制
@property (nonatomic, weak) IBOutlet UILabel *fooLabel;

或者@property (非原子,赋值) IBOutlet UILabel *fooLabel;

这样就不需要在dealloc方法中释放它了。另外,它将满足OSX和iOS的要求。

这是基于逻辑的,我可能在这里遗漏了一些部分。

然而,如果视图在程序的整个生命周期中都是持久的,这可能并不重要。而模式对话框中的标签(打开、关闭、打开、关闭)实际上可能在每个循环中具有过度保留和泄漏。这是因为(再次推测)每个关闭的对话框都被序列化到一个文件系统中,从而保持x,y位置和大小,以及它的子视图等,并随后反序列化...在下一次会话中打开(而不是说最小化或隐藏)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1221516

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档