这真的很有帮助,但大多数人不知道为什么,这很遗憾。
Apple 使用下划线来分隔其他对象访问特定对象变量的方式和特定对象访问其自身变量的方式。
现在这听起来可能有点奇怪,但想象一下:你可能都认出了下面的编译器警告
.h
@property (nonatomic, retain, readonly) UITableView *tableView;
.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self loadSomethingElseForTableView:tableView];
}
这将导致编译器警告,因为它不知道您引用的是局部变量“tableView”还是实例变量。
因此,Apple 建议您将以下内容添加到 @implementation 的顶部。
@synthesize tableView = _tableView;
现在,当您引用 _tableView 时,编译器知道您指的是实例变量,而不是本地变量。
此外,这使得理解 Obj-C 中的垃圾收集变得更加容易,并防止犯常见错误。
例如,当执行以下操作时:
@property (nonatomic, retain, readonly) NSString *title;
- (id)initWithTitle:(NSString *)title {
if ((self = [super init])) {
self.title = title; // Is not possible, since it's read only.
title = title; // Is not possible, since it's the same (local) variable.
// Changing the method to initWithTitle:(NSString *)aTitle;
title = aTitle;
}
return self;
}
现在,由于您不使用默认设置器(实际上,您不能,因为它是只读的)您需要自己保留变量。
当你给每个实例变量一个前缀时,这更容易记住(所以你知道你需要自己保留它)。
因此,基本上,了解self.variable 和 (_)variable 之间的区别很重要。 (即:self.variable 映射到 [self setVariable:...] 和 variable 直接映射到您的指针。
此外,当您将其添加为私有变量时,如下所示:
@interface TSSomeObject : NSObject {
@private
NSString *_privateTitle;
}
@end
下划线前缀并不是必须的,除非你可能会遇到同名的局部变量。除此之外,这也是提醒您它是本地指针并且在将变量分配给对象时需要保留(和释放)变量的简单方法。
是错误的是创建一个带有下划线前缀的属性,像这样:
@property (nonatomic, retain) NSString *_title;
这确实是错误的,我什至不会解释原因;)
所以是的!你真的应该使用下划线前缀,它使你的代码更容易阅读,并被编译器解释!在 Xcode 4 中,Apple 甚至将这些 @synthesizes 添加到默认模板中。