@synthesize IBOutlet property

8

我是一个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 是一种省略枯燥的 getters 和 setters 的快捷方式。
但我有一些问题:
  1. 在实现 tableView 的代码中 从未显式调用,但 dealloc 会释放它;
  2. 如果它从未被显式调用过,为什么要使用 @synthesize?
IBOutlets 是否必须被 synthesized?

顺便说一下,这就是我为什么讨厌为苹果平台开发软件的原因。他们根本不解释他们的黑魔法东西。 - das_weezul
1
@das_weezul,这个nib加载机制在文档中解释得非常清楚。请参考下面的@taskinoor的回答和/或资源编程指南。 - Firoze Lafeer
嘿,我不想挑起争端... :-( - user840248
没问题,我认为所有启动所需的条件都已经具备了 ;-) - user840248
你可以在最近的XCode编译器中完全避免使用synthesize。 - Satyam
显示剩余3条评论
5个回答

7

来自Nib对象的内存管理

当一个Nib文件被加载并且outlet被建立时,无论是在Mac OS X还是iOS上,Nib加载机制总是使用访问器方法(accessor methods),如果这些方法存在的话。因此,无论你为哪个平台开发,你通常应该使用Objective-C声明属性(declared properties)特性来声明outlet。

对于iOS,你应该使用:

@property (nonatomic, retain) IBOutlet UIUserInterfaceElementClass *anOutlet;

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


因此,即使实现部分从未以“具体”的方式使用它,也必须以那种方式创建属性。 - user840248
1
即使您在代码中不使用它,nib加载代码也在使用它。因此,您应该保留它。 - taskinoor
在iOS 6中,ARC仍然是这种情况吗? - Robert Karl
@Robert Karl,抱歉。我不确定那个。 - taskinoor

3
在实现代码中,tableView从未显式调用,但在dealloc中释放了它;这是因为当你给tableView赋值时,你的控制器会保留它,并且在dealloc时需要释放它。不要忘记,在接口中声明的@properties是公开可访问的。在你的情况下,你声明为IBOutlet的tableView是由视图控制器的loadView方法使用你在Interface Builder中定义的连接初始化的File's Owner和UITableView之间的连接。
如果它从未被显式调用,为什么还需要@synthesize?你需要为所有声明的@properties提供访问器。它们可以被@synthesized,或者你可以自己编写。
IBOutlets是否必须被synthesize?不是,但这样更方便。编译器强制执行的规则是,在实现中@properties必须有相应的访问器(无论是合成的还是自己写的)。

2

供参考:从 Xcode 4.4 和 LLVM Compiler 4.0 开始,@synthesize 指令不再是必需的,因为对于在接口中定义的 @property,默认情况下将提供该指令。


1

如果你输入

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

你告诉编译器:“听着,这里会有一个getter和一个setter。如果合适的话,就用它们!”然后当加载nib文件时,编译器就会使用它们。
因此,你必须实现getter和setter,否则编译器会抱怨。

当您没有声明getter和setter时,运行时应该如何在加载nib时使用它们? - dasdom

0

IBOutlet 伪类型只是一个标记,以便 InterfaceBuilder “知道”所提到的类文件具有对 UITableView 实例的句柄/插座。

编译时,预处理器会删除 IBOutlet(InterfaceBuilder 解析(查看)源文件)。这与 IBAction 类似:它被预处理器替换为 void。

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


好的,“could”这个词是很基础的,因为来自其他编程语言的程序员会认为你会使用你声明的东西... - user840248

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接