加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

objective-c – 关于@synthesize的问题

发布时间:2020-12-15 01:38:57 所属栏目:百科 来源:网络整理
导读:当您从嵌入CoreData的Xcode创建一个新的应用程序时,您将这些行放在委托的实现文件中: @synthesize window=_window;@synthesize managedObjectContext=__managedObjectContext; 仅使用下划线或双重使用的区别是什么?仅写作有什么区别? @synthesize window;
当您从嵌入CoreData的Xcode创建一个新的应用程序时,您将这些行放在委托的实现文件中:

@synthesize window=_window;

@synthesize managedObjectContext=__managedObjectContext;

仅使用下划线或双重使用的区别是什么?仅写作有什么区别?

@synthesize window;

解决方法

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

考虑差异(非ARC代码):

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属性仍然是错误的:

@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通知来执行延迟加载.如果您不小心跳过访问者,您的数据将恢复为零.

这是你经常发现@synthesize var = _var的原因,这使得

> self.var一个访问器引用(调用setter和getter),
> _var直接访问引用(跳过setter和getter),
>和var一个无效的引用.

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

继续阅读详细信息…

现代运行时

在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;

这就是你所需要的,因为with the modern runtime,如果你不提供一个实例变量,编译器为你添加一个.这是编译的代码:

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

如果添加ivar和@property,会发生什么?如果变量具有相同的名称和类型,编译器会使用它来生成一个新的变量.引用Objective-C编程语言>声明属性> 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.

  • 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.

传统运行时

但是,如果您需要support the legacy runtime,则必须提供具有相同名称和兼容类型的实例变量,或者在@synthesize语句中指定另一个现有实例变量.

所以没有下划线的遗留代码将是:

@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

什么是最好的方法?

苹果不鼓励在方法中使用下划线,而不是使用变量!

苹果方法: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.

苹果对变量:Declared Properties and Instance Variables

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 Reserved identifiers(又名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则将其作为新的非标准关键字引入.

Google Objective-C Style guide:

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.

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

C(参见What are the rules about using an underscore in a C++ identifier?)和Core Data属性(尝试在模型中添加领先的下划线)也不鼓励领先的下划线,您将获得“名称必须以字母开头”).

无论你选择什么,碰撞都不太可能发生,如果这样做,你会得到编译器的警告.当有疑问时,使用默认的LLVM方式:@synthesize var = _var;

我拥有这篇文章的编辑,由Mark Dalrymple阅读A Motivation for ivar decorations.你可能想检查一下.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读