我以前在变量名中避免使用下划线,这可能是我大学Java时代的延续。因此,当我在Objective C中定义一个属性时,这就是我自然而然的事情。
// In the header
@interface Whatever
{
NSString *myStringProperty
}
@property (nonatomic, copy) NSString *myStringProperty;
// In the implementation
@synthesize myStringProperty;
但几乎每个例子都像
一样// In the header
@interface Whatever
{
NSString *_myStringProperty
}
@property (nonatomic, copy) NSString *myStringProperty;
// In the implementation
@synthesize myStringProperty = _myStringProperty;
我是否应该克服对下划线的厌恶,因为这是应该做的一种方式,这种风格是否是一个很好的理由?
更新:现在使用自动属性合成,您可以省略@synthesize,结果与使用
相同@synthesize myStringProperty = _myStringProperty;
它清楚地显示了Apple的偏好。我已经学会了停止担心并喜欢下划线。
答案 0 :(得分:47)
我总是使用下划线。它在局部变量和实例变量之间创建了明确的区别。在以下情况下,它还可以避免编译器警告:
@interface MyClass
{
NSString *name
}
@property (nonatomic, copy) NSString *name;
- (id) initWithName:(NSString *) name;
@end
@implementation MyClass
@synthesize name;
// The following method will result in a compiler warning
// (parameter name same as ivar name)
- (id) initWithName:(NSString *) name {
if (self = [super init]) {
self.name = name;
}
return self;
}
@end
修改强>:
在不得不忍受赞成票并阅读评论之后,让我试着说明一下:
Apple建议ivars与其属性具有相同的名称。 Apple还建议属性以小写字母开头。 Apple还建议局部变量以小写字母开头。
现在你遇到了一个问题,因为当你读取一段代码,并且看到一个正在使用的变量时,你不能通过命名约定告诉这个变量是一个ivar还是一个局部变量。太糟糕了。解决方案是对ivars和局部变量使用不同的命名约定。这只是普通的常识。
实现此命名约定的方式无关紧要。如果你真的想要,你可以简单地将“_WOOHAHA”附加到ivar名称。我不在乎(但也许其他人会)。问题是知道他们正在做什么的人决定使用ivars的“下划线前缀”。恕我直言,他们做出了正确的决定,即使他们自己的公司推荐别的东西。 (我正在谈论的开发人员是编写一些主要Apple框架和.NET Framework类的人员)
最后,代码质量比遵循一个愚蠢的规则更重要,而这个规则甚至没有人们传播它。
关于您展示的代码的另一个评论:永远不要在字符串属性上使用保留。您应该使用复制。
有关复制/保留属性的详细信息,请参阅:
答案 1 :(得分:29)
在2012-02-16修订版之后,Apple在“可可编码指南”中明确说明了以_为前缀的实例变量的命名约定。
确保实例变量的名称简明地描述了存储的属性。通常,您不应该直接访问实例变量,而应该使用访问器方法(您可以直接在init和dealloc方法中访问实例变量)。为了帮助发出信号,请使用下划线(_)作为实例变量名称的前缀,例如:
@implementation MyClass {
BOOL _showsTitle;
}
如果使用声明的属性合成实例变量,请在@synthesize语句中指定实例变量的名称。
@implementation MyClass
@synthesize showsTitle=_showsTitle;
斯坦福大学Paul Hegarty教授的iTunes U,iPhone App Development CS193p 2011秋季讲座也解释了这一惯例。
http://itunes.apple.com/itunes-u/ipad-iphone-application-development/id473757255
我知道很久以前就提出这个问题了,但我自己也有同样的问题,想分享我的发现。
答案 2 :(得分:18)
目前建议的Objective-C 2.0实践是使用与ivar相同的名称作为属性。您可以选择在@property声明中指定不同的ivar,但默认情况下,属性的合成访问器将访问与该属性同名的ivar,这表明它们是您希望遵循的模式。
无论如何,由于对象仍然必须向自己发送消息以访问属性,因此当您访问属性或直接访问其支持ivar时很难混淆,尽管使用2.0点访问属性确实让它变得更有可能。使用标准消息传递语法使意图更明确,IMO。
@interface Foo : NSObject {
NSNumber *bar;
}
@property(readwrite, retain) NSNumber * bar
@end
@implementation Foo
@synthesize bar;
-(void) baz {
NSNumber *numberOne = [NSNumber numberWithInt: 1];
//Both set the value of bar through either the your custom or the synthesized setter method
[self setBar:numberOne];
self.bar = numberOne;
//Both get the value of bar through your synthesized or your custom accessor method
NSNumber *fooBar = [self bar];
fooBar = self.bar;
//Both manipulate the bar ivar directly
bar = numberOne;
fooBar = bar;
}
@end
答案 3 :(得分:6)
Apple保留选择器以下划线开头,用于他们自己的“私人”方法,其中包括属性。我不认为他们会为伊娃的名字保留_。
就个人而言,我会避免使用下划线来启动任何类型的变量名称。这是一个不透明的惯例。如果其他人对本地人使用下划线而对实例变量没有下划线怎么办?如果您在具有相同名称的本地定义的方法中意外省略了下划线,该怎么办?
使您的本地名称与您的ivar名称不同更好。例如,在setter中,您可以使用newName或neWValue。
答案 4 :(得分:3)
这纯粹是一种风格问题。
我不知道哪些例子使用了强调的ivar风格。官方Apple示例(例如CryptoExercise)不会在ivars前加_
。
答案 5 :(得分:2)
我只想指出,使用核心数据的新导航项目默认使用尾随下划线,并将变量设为私有。
@interface MyTestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UINavigationController *navigationController;
@private
NSManagedObjectContext *managedObjectContext_;
NSManagedObjectModel *managedObjectModel_;
NSPersistentStoreCoordinator *persistentStoreCoordinator_;
}
@interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate> {
@private
NSFetchedResultsController *fetchedResultsController_;
NSManagedObjectContext *managedObjectContext_;
}
答案 6 :(得分:1)
当对象无法找到要检索该变量的消息时,运行时的KVC部分在使用valueForKey:时需要名称或_name ivar。见http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/SearchImplementation.html
如果运行时困扰搜索_name并且apple文档首先提到_name,那么可能有充分的理由。让我们来看看一些SDK类:UINavigationBar.h这个类在所有ivars前面都有下划线,UIView也是......列表继续。好吧也许就是这种方式,新的iOS SDK和好的NS *类不会做那样的方式......错误;他们也在头文件中使用下划线。
Apple在私有API消息和ivars中使用下划线。我无法理解为什么他们的例子不会推动这种行为,特别是当运行时困扰将这种所谓的“命名约定”硬编码到变量搜索路径中时。看到一些一致性会很高兴。
请注意,您必须遵循严格的命名方案才能符合KVC标准;上面的链接可以帮助您符合这一点,以使用运行时的这个方便的功能。