@synthesize IBOutlet 属性

Posted

技术标签:

【中文标题】@synthesize IBOutlet 属性【英文标题】:@synthesize IBOutlet property 【发布时间】:2011-07-12 15:09:34 【问题描述】:

我是一名 Objective-C 新手,正在阅读 Alasdair Allan 的“iPhone 编程”。在阅读时,我发现了这段代码:

@interface RootController : UIViewController <UITableViewDataSource, UITableViewDelegate> 
    UITableView *tableView;
    NSMutableArray *cities;

// warning: remember this tableView
@property (nonatomic, retain) IBOutlet UITableView *tableView;

相对实现是这样开始的:

@implementation RootController
@synthesize tableView;

现在:我了解到@synthesize 是一种避免无聊的 getter 和 setter 的捷径。

但我有一个问题:

    在实现tableView的代码中从未显式调用但dealloc会释放它; 如果它从未被显式调用,为什么要使用 @synthesize?

IBOutlets是否必须合成?

【问题讨论】:

问得好,我已经使用Objective C 一个多星期了,从来没有想过这个,我只知道当我不合成时它会抱怨。 顺便说一句,这就是我讨厌为 Apple 平台开发软件的原因。他们只是不解释他们的黑魔法。 @das_weezul,这个 nib 加载机制在文档中解释得很清楚。请参阅下面的@taskinoor 答案和/或资源编程指南。 @Firoze 我反对。他们没有解释 IBOutlet 被预处理器删除,IBAction 被预处理器替换为 void 并且这两个“关键字”只是 InterfaceBuilder 的一个标记,它们不是 ObjectiveC 语法的一部分 嘿,我不想制造火焰...... :-( 【参考方案1】:

来自Memory Management of Nib Objects,

当加载 nib 文件并建立 outlets 时,nib 加载机制始终使用访问器方法(如果存在)(在 Mac OS X 和 ios 上)。因此,无论您为哪个平台开发,您通常都应该使用 Objective-C 声明的属性功能来声明 outlet。

对于 iOS,您应该使用:

@property(非原子,保留)IBOutlet UIUserInterfaceElementClass *anOutlet;

然后你应该要么合成相应的访问器方法,要么根据声明实现它们,并(在iOS中)释放dealloc中的相应变量。

【讨论】:

因此,即使实现部分从未真正以“具体”方式使用它,也必须以这种方式创建属性。 即使你没有在你的代码中使用它,nib 加载代码也在使用它。所以你应该保留它。 iOS 6 中的 ARC 是否仍然如此? @Robert Karl,对不起。我不确定。【参考方案2】:

在实现tableView的代码中从不显式调用但dealloc释放它;

那是因为当您 为 tableView 分配一个值时,您的控制器会保留它,当它被释放时它需要释放它。不要忘记,在接口中声明的@properties 是可以公开访问的。具体而言,您声明为 IBOutlet 的 tableView 由视图控制器 loadView 方法使用您在 Interface Builder 中定义的文件所有者和 UITableView 之间的连接进行初始化。

如果它从未被显式调用,为什么要使用 @synthesize?

您需要为所有声明的@properties 提供访问器。它们可以是@synthesized,也可以自己编写。

IBOutlets是否必须合成?

不,但这样更方便。编译器强制执行的规则是 @properties 必须在实现中具有相应的访问器(合成的或不合成的)。

【讨论】:

【参考方案3】:

供参考:从 Xcode 4.4 和 LLVM 编译器 4.0 开始,不再需要 @synthesize 指令,因为默认情况下会为接口中定义的 @properties 提供它。

【讨论】:

【参考方案4】:

如果你输入

@property (nonatomic, retain) IBOutlet UITableView *tableView;

你告诉编译器:“听着,会有一个 getter 和一个 setter。如果合适,使用它们!”它会在加载笔尖时使用它们。

因此你必须实现 getter 和 setter,否则编译器会报错。

【讨论】:

那么当你没有声明它们时,运行时应该如何在加载 nib 时使用你的 getter 和 setter?【参考方案5】:

IBoutlet 伪类型只是一个标记,因此 InterfaceBuilder“知道”所提到的类文件具有 UITableView 实例的句柄/出口。

编译 IBOutlet 时,预处理器正在删除(InterfaceBuilder 解析(查看)源文件)。与 IBAction 类似:预处理器将其替换为 void。

也就是说,您可以使用对所述实例的引用以编程方式执行操作(例如添加/更改 UITableView 的值)

【讨论】:

好吧,'可以'是基本的,因为来自其他语言的程序员认为你会使用你声明的内容......

以上是关于@synthesize IBOutlet 属性的主要内容,如果未能解决你的问题,请参考以下文章

@synthesize的使用

Xcode 4.5 似乎仍然期待@synthesize - 否则无法访问属性

属性的定义以及@synthesize的使用

@property & @synthesize 及相关属性作用探究

使用 CoreData,如果我有一个 @dynamic 属性,我可以像 @synthesized 一样覆盖它的 getter 吗? (惰性实例化)

Objective-C 是 @synthesize 是必需的还是可选的?