罗泽轩*_*罗泽轩 69 properties objective-c synthesize
据我所知,由于XCode 4.4 @synthesize将自动生成属性访问器.但是刚才我已经阅读了一些代码示例NSUndoManager,并在代码中注意到它@synthesize是明确添加的.喜欢:
@interface RootViewController ()
@property (nonatomic, strong) NSDateFormatter *dateFormatter;
@property (nonatomic, strong) NSUndoManager *undoManager;
@end
@implementation RootViewController
//Must explicitly synthesize this
@synthesize undoManager;
Run Code Online (Sandbox Code Playgroud)
我现在感到困惑...... @synthesize我什么时候应该明确地添加到我的代码中?
Gab*_*lla 158
有很多答案,但也是一个很大的混乱.我会尝试下订单(或增加一塌糊涂,我们会看到......)
让我们停止谈论Xcode.Xcode是一个IDE.clang是一个编译器.我们讨论的这个特性叫做属性的自动合成,它是clang支持的Objective-C语言扩展,它是Xcode使用的默认编译器.
为了说清楚,如果你在Xcode中切换到gcc,你将无法从这个功能中受益(无论是Xcode版本.)同样如果你使用文本编辑器并使用命令行中的clang编译,你将.
感谢自动合成,您不需要显式合成属性,因为它将由编译器自动合成
@synthesize propertyName = _propertyName
Run Code Online (Sandbox Code Playgroud)
但是,存在一些例外:
使用自定义getter和setter的readwrite属性
当同时提供getter和setter自定义实现时,该属性将不会自动合成
readonly属性与自定义getter
为readonly属性提供自定义getter实现时,不会自动合成
@动态
使用时@dynamic propertyName,属性不会自动合成(非常明显,因为@dynamic并且@synthesize互相排斥)
在@protocol中声明的属性
当符合协议时,协议定义的任何属性都不会自动合成
在类别中声明的属性
这种情况下@synthesize编译器不会自动插入指令,但也无法手动合成此属性.虽然类别可以声明属性,但它们根本无法合成,因为类别无法创建ivars.为了完整起见,我将补充说,仍然可以使用Objective-C运行时伪造属性合成.
被覆盖的属性(自clang-600.0.51之后的新版本,随Xcode 6发布,感谢MarcSchlüpmann)
当您覆盖超类的属性时,您必须显式合成它
值得注意的是,合成属性会自动合成背景ivar,因此如果缺少属性合成,除非明确声明,否则ivar也将丢失.
除了最后三种情况,一般的理念是,无论何时手动指定有关属性的所有信息(通过实现所有访问器方法或使用@dynamic),编译器都会假定您想要完全控制属性,它将禁用自动合成它.
除了上面列出的情况之外,显式的唯一其他用途@synthesize是指定不同的ivar名称.但是约定很重要,所以我的建议是始终使用默认命名.
KID*_*dAe 18
如果您没有明确使用@synthesize,编译器将以相同的方式理解您的属性
@synthesize undoManager=_undoManager;
Run Code Online (Sandbox Code Playgroud)
然后你就可以在你的代码中写下这样的东西:
[_undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter
Run Code Online (Sandbox Code Playgroud)
这是常见的惯例.
如果你写
@synthesize undoManager;
Run Code Online (Sandbox Code Playgroud)
你将会有 :
[undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter
Run Code Online (Sandbox Code Playgroud)
我个人不再使用@synthesize,因为它不再是强制性的.对我来说,使用的唯一理由@synthesize是将a链接iVar到a @property.如果你想为它生成特定的getter和setter.但是在给定的代码中没有iVar,我认为这@synthesize没用.但是现在我认为新的问题是"何时使用iVar?",而且我没有其他回应而不是"从不"这个问题!
Ste*_*her 13
@synthesize我什么时候应该明确添加到我的代码?
通常,如果需要:您可能永远不会遇到需要的情况.
不过,有一种情况你会发现它很有用.
假设您正在编写自定义getter和setter,但需要一个实例变量来支持它.(对于原子属性,这就像想要一个自定义setter一样简单:如果你为一个单原子属性指定一个setter而不是一个原子属性,编译器会写一个getter.)
考虑一下:
@interface MyObject:NSObject
@property (copy) NSString *title;
@end
@implementation MyObject
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为_title不存在.您已经指定了getter或setter,因此Xcode(正确)不会为它创建支持实例变量.

你有两种选择让它存在.您可以更改@implementation为:
@implementation MyObject {
NSString *_title;
}
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
Run Code Online (Sandbox Code Playgroud)
或者将其更改为:
@implementation MyObject
@synthesize title = _title;
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
Run Code Online (Sandbox Code Playgroud)
换句话说,虽然合成是出于实际目的而永远不需要*,但是当您提供getter/setter时,它可用于定义属性支持实例变量.您可以决定要使用哪种表单.
在过去,我更喜欢在中指定实例变量@implementation {},但我现在认为@synthesize路由是更好的选择,因为它删除了冗余类型并明确地将后备变量绑定到属性:
@synthesize将生成编译器错误.您不会最终得到杂散的实例变量.* - 我知道有必要的一个案例,涉及跨多个文件中的类别拆分功能.如果Apple修复此问题,甚至已经修复过,我也不会感到惊讶.
好的,当您创建属性时...
@property NSString *name;
Run Code Online (Sandbox Code Playgroud)
Xcode会自动综合生成一个iVar,就像您编写的一样。
@synthesize name = _name;
Run Code Online (Sandbox Code Playgroud)
这意味着您可以使用...访问酒店
self.name;
// or
_name;
Run Code Online (Sandbox Code Playgroud)
两种方法都可以,但是只能self.name实际使用访问器方法。
自动合成只有一次不起作用:如果您覆盖了setter和getter方法,那么您将需要合成iVar。
如果您仅覆盖setter或覆盖getter,就可以了。但是,如果两者都做,那么编译器将无法理解它,而您将需要手动对其进行综合。
根据经验。
不要做iVars。只需使用该属性。不要合成它。
| 归档时间: |
|
| 查看次数: |
52782 次 |
| 最近记录: |