Objective c 关于@synthesis的问题

Objective c 关于@synthesis的问题,objective-c,xcode,Objective C,Xcode,从嵌入CoreData的Xcode创建新应用程序时,代理的实现文件中有以下行: @synthesize window=_window; @synthesize managedObjectContext=__managedObjectContext; 只使用下划线或将下划线加倍有什么区别?只写有什么区别: @synthesize window; 你可以用 @合成窗口 但是,如果您的实例变量名为“window”,则有些人会使用一种命名约定,即在所有实例变量前加下划线,但仍然希望其getter和

从嵌入CoreData的Xcode创建新应用程序时,代理的实现文件中有以下行:

@synthesize window=_window;

@synthesize managedObjectContext=__managedObjectContext;
只使用下划线或将下划线加倍有什么区别?只写有什么区别:

@synthesize window;
你可以用

@合成窗口

但是,如果您的实例变量名为“window”,则有些人会使用一种命名约定,即在所有实例变量前加下划线,但仍然希望其getter和setter不加下划线前缀,这就是“window=\u window”的意思


我不知道双下划线是什么意思,但我怀疑这也是命名约定的问题。

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

考虑差异(非ARC代码):

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

@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(如核心数据)依赖KVC通知来执行延迟加载。如果您不小心跳过了访问器,您的数据将返回为零

这就是为什么您经常会发现
@synthesis var=\u var
,这使得

  • self.var
    访问器引用(调用setter和getter)
  • \u var
    直接访问引用(跳过setter和getter)
  • var
    无效引用
<> > <代码> >合成VaR=VaR < /C> > LLVM 4自动生成,当“代码>@合成< /COD>”被省略时,可以考虑这是Objul-C.</P>中的默认命名约定。 请继续阅读以了解详细信息


现代运行时 在Objective-C 2.0中,您声明的变量如下:

@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
如果您喜欢使用下划线约定,只需添加以下内容:

@synthesize age=_age;
这就是您所需要的,因为如果您不提供实例变量,编译器会为您添加一个实例变量。下面是编译的代码:

@interface User : NSObject {
    NSInteger _age;
}
@end
@implementation User
-(void)setAge:(NSInteger)newAge {
    _age=newAge;
}
-(void)age {
    return _age;
}
@end
如果同时添加ivar和@property,会发生什么?如果变量具有相同的名称和类型,编译器将使用它来生成新变量。引用Objective-C编程语言>声明的属性>:

访问器合成的行为存在差异 取决于运行时:

  • 对于现代运行时,根据需要合成实例变量。如果已存在同名的实例变量,则为 用过

  • 对于遗留运行时,实例变量必须已经在当前类的@interface块中声明。如果一个实例 存在与属性同名的变量,如果其类型为 如果与属性的类型兼容,则使用它-否则,您将获得 编译器错误

遗留运行时 但如果需要,则必须提供具有相同名称和兼容属性类型的实例变量,或者在@synthesis语句中指定另一个现有实例变量

因此,没有下划线的遗留代码将是:

@interface User : NSObject {
    NSInteger age;
}
@property (nonatomic, assign) NSInteger age;
@end
@implementation User
@synthesize age;
@end
或者,如果您更喜欢下划线约定:

@interface User : NSObject {
    NSInteger _age;
}
@property (nonatomic, assign) NSInteger age;
@end
@implementation User
@synthesize age = _age;
@end
最好的方法是什么? Apple不鼓励在方法中使用下划线,但不鼓励在变量中使用下划线

苹果公司的方法:

避免使用下划线 字符作为前缀,表示私有, 尤其是在方法上。苹果储备 本公约的使用。使用 第三方可能导致 名称空间冲突;他们可能 无意中覆盖现有的 用他们自己的方法, 造成灾难性后果

关于变量的苹果:

确保实例变量的名称简洁地描述了 属性存储。通常,您不应该访问实例变量 相反,您应该直接使用访问器方法(您不需要访问 直接在init和dealloc方法中使用实例变量)帮助 发出此信号,在实例变量名称前加下划线(41;, 例如:
@implementation MyClass{BOOL\u showsTitle;}

(又名C99):

  • 以下划线和大写字母开头的所有标识符 字母或其他下划线是 总是为任何用途保留
  • 全部 以 下划线始终保留供使用 作为标识符,在两者中都具有文件作用域 普通和标记名称空间
除此之外,双前导下划线传统上保留给预处理器/编译器/库的供应商。这避免了在代码中的某个地方使用
\uu block
的情况,苹果将其作为一个新的非标准关键字引入

:

变量名变量名开始 使用小写字母,并使用大小写混合 划出单词。类成员变量 有尾随的下划线。对于 示例:myLocalVariable, myInstanceVariable\uU4。成员用于 KVO/KVC绑定可以从 使用 Objective-C2.0的@property不是 允许

Google的尾随下划线不会强制您在Xcode触发自动完成之前再键入一个字符,但您会意识到,如果下划线是后缀,则它是一个实例变量

< P>下划线也被禁止在C++(参见)和核心数据属性(尝试添加一个领先的下划线在模型中,你会得到“名称必须以字母开头”)。 无论您选择什么,冲突都不太可能发生,如果发生冲突,编译器会发出警告。如有疑问,请使用默认的LLVM方式:
@synthesis var=\u var



我拥有马克·达尔林普的这篇文章的编辑。您可能想查看它。

这已被要求死亡。为了帮助搜索现有的问题,
\uu
被称为und
@interface User : NSObject {
    NSInteger _age;
}
@property (nonatomic, assign) NSInteger age;
@end
@implementation User
@synthesize age = _age;
@end