在Objective C中使用下划线前缀属性名称

时间:2010-08-19 11:28:05

标签: iphone objective-c coding-style

我以前在变量名中避免使用下划线,这可能是我大学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的偏好。我已经学会了停止担心并喜欢下划线。

7 个答案:

答案 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类的人员)

最后,代码质量比遵循一个愚蠢的规则更重要,而这个规则甚至没有人们传播它。


关于您展示的代码的另一个评论:永远不要在字符串属性上使用保留。您应该使用复制

有关复制/保留属性的详细信息,请参阅:

NSString property: copy or retain?

答案 1 :(得分:29)

在2012-02-16修订版之后,Apple在“可可编码指南”中明确说明了以_为前缀的实例变量的命名约定。

  

确保实例变量的名称简明地描述了存储的属性。通常,您不应该直接访问实例变量,而应该使用访问器方法(您可以直接在init和dealloc方法中访问实例变量)。为了帮助发出信号,请使用下划线(_)作为实例变量名称的前缀,例如:

@implementation MyClass {
    BOOL _showsTitle;
}
  

如果使用声明的属性合成实例变量,请在@synthesize语句中指定实例变量的名称。

@implementation MyClass
@synthesize showsTitle=_showsTitle;

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html#//apple_ref/doc/uid/20001284-BAJGIIJE

斯坦福大学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标准;上面的链接可以帮助您符合这一点,以使用运行时的这个方便的功能。