@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 属性的主要内容,如果未能解决你的问题,请参考以下文章
Xcode 4.5 似乎仍然期待@synthesize - 否则无法访问属性
@property & @synthesize 及相关属性作用探究
使用 CoreData,如果我有一个 @dynamic 属性,我可以像 @synthesized 一样覆盖它的 getter 吗? (惰性实例化)