关于@synthesize的问题 [英] Question about @synthesize

查看:97
本文介绍了关于@synthesize的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当您使用Xcode创建一个嵌入CoreData的新应用程序时,会将这些行显示在委托的实现文件中:

When you create a new application from Xcode that embed CoreData you got those lines in the implementation file of the delegate:

@synthesize window=_window;

@synthesize managedObjectContext=__managedObjectContext;

仅使用下划线或将其加倍有什么区别?只写有什么区别:

What are the differences between using only a underscore or double it? What's the difference on writing only:

@synthesize window;

推荐答案

前导下划线是一种命名约定,有助于区分实例变量和访问器.对于编译器,这只是一个常见的ivar重命名.

A leading underscore is a naming convention helpful to differentiate between instance variables and accessors. For the compiler it is just a common ivar rename.

考虑区别(非ARC代码):

Consider the difference (non ARC code):

self.date = [NSDate date];  // OK, the setter releases the old value first
date = [NSDate date];       // WRONG, skipping the setter causes a memory leak
_date = [NSDate date];      // WRONG but easier to see it's not a local variable

使用ARC变量不会被泄漏,但是跳过@property属性仍然是错误的:

With ARC variables won't be leaked, but it is still wrong to skip the @property attributes:

@property (copy) string;
// ...
self.string = someString;   // OK, string is copied
string = someString;        // WRONG string is retained but not copied
_string = someString;       // WRONG but hopefully easier to see

即使是最糟糕的情况,某些API(如Core Data)也依赖KVC通知来执行延迟加载.如果您不小心跳过了访问器,您的数据将返回nil.

Even worst, some APIs like Core Data rely on KVC notifications to perform lazy loading. If you accidentally skip the accessors, your data will come back as nil.

这就是您经常找到@synthesize var=_var的原因,它使

This is the reason you often find @synthesize var=_var, which makes

  • self.var访问者引用(调用设置器和获取器),
  • _var直接访问参考(跳过设置器和获取器),
  • var无效的引用.
  • self.var an accessor reference (invoking setters and getters),
  • _var a direct access reference (skipping setters and getters),
  • and var an invalid reference.

鉴于@synthesize var=_var是由LLVM 4.0自动生成的,当省略@synthesize时,您可以将其视为Objective-C中的默认命名约定.

Given that @synthesize var=_var is autogenerated by LLVM 4.0 when @synthesize is omitted, you can consider this the default naming convention in Objective-C.

请继续阅读以获取详细信息...

Keep reading for details...

在Objective-C 2.0中,您可以这样声明变量:

In Objective-C 2.0 you declare variables like this:

@interface User : NSObject
@property (nonatomic, assign) NSInteger age;
@end
@implementation User {
@synthesize age; // this line can be omitted since LLVM 4.0
@end

由编译器翻译如下:

@interface User : NSObject {
    NSInteger age;
}
@end
@implementation User
-(void)setAge:(NSInteger)newAge {
    age=newAge;
}
-(void)age {
    return age;
}
@end

如果您想使用下划线约定,只需添加以下内容:

If you prefer to use the underscore convention just add the following:

@synthesize age=_age;

这就是您所需要的,因为

That's all you need because with the modern runtime, if you do not provide an instance variable, the compiler adds one for you. Here is the code that gets compiled:

@interface User : NSObject {
    NSInteger _age;
}
@end
@implementation User
-(void)setAge:(NSInteger)newAge {
    _age=newAge;
}
-(void)age {
    return _age;
}
@end

如果同时添加ivar和@property,会发生什么情况?如果变量具有相同的名称和类型,则编译器将使用它,而不是生成一个新变量.引用Objective-C编程语言>声明的属性>

What happens if you add both the ivar and the @property? If the variable has the same name and type, the compiler uses it instead generating a new variable. Quoting The Objective-C Programming Language > Declared Properties > Property Implementation Directives:

访问者综合的行为存在差异, 取决于运行时:

There are differences in the behavior of accessor synthesis that depend on the runtime:

  • 对于现代运行时,实例变量根据需要进行综合. 如果已经存在相同名称的实例变量,则为

  • For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.

对于旧版运行时,必须已在当前类的@interface块中声明了实例变量. 如果是实例 存在与属性同名的变量,并且其类型为 会与该属性的类型兼容 -否则,您将获得一个 编译器错误.

For the legacy runtimes, instance variables must already be declared in the @interface block of the current class. If an instance variable of the same name as the property exists, and if its type is compatible with the property’s type, it is used —otherwise, you get a compiler error.

旧版运行时

但是如果您需要因此没有下划线的旧代码将是:

So the legacy code without underscores would be:

@interface User : NSObject {
    NSInteger age;
}
@property (nonatomic, assign) NSInteger age;
@end
@implementation User
@synthesize age;
@end

或者如果您喜欢下划线约定:

Or if you prefer the underscore convention:

@interface User : NSObject {
    NSInteger _age;
}
@property (nonatomic, assign) NSInteger age;
@end
@implementation User
@synthesize age = _age;
@end

什么是最好的方法?

Apple不鼓励在方法中使用下划线,但不要在变量上使用下划线!.

What is the best way?

Apple discourages the use of underscore in methods, but not on variables!.

Apple方法: 可可编码指南:印刷约定 :

Apple on methods: Coding Guidelines for Cocoa: Typographic Conventions:

避免使用下划线 字符作为前缀,表示私有, 尤其是方法上.苹果储备 使用此约定.使用者 第三方可能会导致 名称空间冲突;他们可能 不经意间覆盖了现有的 拥有自己的一种私有方法, 带来灾难性的后果.

Avoid the use of the underscore character as a prefix meaning private, especially in methods. Apple reserves the use of this convention. Use by third parties could result in name-space collisions; they might unwittingly override an existing private method with one of their own, with disastrous consequences.

关于变量的Apple:

Apple on variables: Declared Properties and Instance Variables

确保实例变量的名称简洁地描述了 属性已存储.通常,您不应该访问实例变量 直接,而是应该使用访问器方法(您可以访问 实例变量直接在init和dealloc方法中). 为了帮助 发出信号,在实例变量名称前加上下划线(_), 例如:@implementation MyClass { BOOL _showsTitle; }

Make sure the name of the instance variable concisely describes the attribute stored. Usually, you should not access instance variables directly, instead you should use accessor methods (you do access instance variables directly in init and dealloc methods). To help to signal this, prefix instance variable names with an underscore (_), for example: @implementation MyClass { BOOL _showsTitle; }

ISO/IEC 9899 7.1. 3个保留的标识符 (又称C99):

ISO/IEC 9899 7.1.3 Reserved identifiers (aka C99):

  • 所有以下划线和大写字母开头的标识符 字母或其他下划线是 始终保留供任何使用.
  • 全部 以开头的标识符 下划线始终保留供使用 作为两个文件范围的标识符 普通和标记名称空间.
  • All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
  • All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.

最重要的是,双引号下划线通常保留给预处理器/编译器/库的供应商.这样可以避免在代码中的某处使用__block的情况,Apple会将其作为新的非标准关键字引入.

On top of that, double leading underscore is traditionally reserved for the vendor of the preprocessor / compiler / library. This avoids the case where you use __block somewhere in your code, and Apple introduces that as a new non-standard keyword.

Google Objective-C样式指南 :

变量名称变量名称开头 用小写并混合使用大小写 分隔字词.类成员变量 带有跟踪下划线.为了 例如:myLocalVariable, myInstanceVariable_.成员用于 KVO/KVC绑定可以以 领先的下划线,如果使用 不是Objective-C 2.0的@property 允许.

Variable Names Variables names start with a lowercase and use mixed case to delimit words. Class member variables have trailing underscores. For example: myLocalVariable, myInstanceVariable_. Members used for KVO/KVC bindings may begin with a leading underscore iff use of Objective-C 2.0's @property isn't allowed.

Google的尾部下划线不会强迫您在Xcode触发自动完成功能之前再输入一个字符,但是如果下划线是后缀,您会意识到它是一个实例变量,速度较慢.

Google's trailing underscore doesn't force you to type one more character before Xcode fires the autocomplete, but you'll realize it is an instance variable slower if the underscore is a suffix.

在C ++中也不鼓励使用下划线(请参阅在C ++标识符中使用下划线的规则是什么?)核心数据属性(尝试在模型中添加前导下划线,您将获得名称必须以字母开头").

Leading underscore is also discouraged in C++ (see What are the rules about using an underscore in a C++ identifier?) and Core Data properties (try adding a leading underscore in the model and you'll get "Name must begin with a letter").

无论您选择什么,都不太可能发生冲突,如果发生冲突,则会从编译器收到警告.如有疑问,请使用默认的LLVM方式:@synthesize var=_var;

Whatever you chose, collisions are unlikely to happen, and if they do, you'll get a warning from the compiler. When in doubt, use the default LLVM way: @synthesize var=_var;

我对此帖子进行了修改,以阅读马克·达里姆普(Mark Dalrymple)制作的ivar装饰.您可能需要检查一下.

I own an edit of this post to reading A Motivation for ivar decorations by Mark Dalrymple. You may want to check it out.

这篇关于关于@synthesize的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆