objective-c 我什么时候应该明确使用@synthesize?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19784454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When should I use @synthesize explicitly?
提问by u2278997
As far as I know, since XCode 4.4 the @synthesizewill auto-generate the property accessors. But just now I have read a sample of code about NSUndoManager, and in the code it noticed that the @synthesizeis added explicitly. Like:
据我所知,从 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;
I am feeling puzzled now... When should I add @synthesizeexplicitly to my code?
我现在感到困惑......我应该什么时候@synthesize明确地添加到我的代码中?
回答by Gabriele Petronella
There's a lot of answers, but also a big confusion. I'll try to put some order (or increase the mess, we'll see...)
有很多答案,但也有很大的困惑。我会试着安排一些订单(或增加混乱,我们会看到......)
Let's stop talking about Xcode. Xcode is an IDE. clang is a compiler. This feature we are discussing is called autosynthesis of propertiesand it's an Objective-C language extension supported by clang, which is the default compiler used by Xcode.
Just to make it clear, if you switch to gcc in Xcode, you won't benefit from this feature (regardless from the Xcode version.) In the same way if you use a text editor and compile using clang from the command line, you will.Thank to autosynthesis you don't need to explicitly synthesize the property as it will be automatically synthesized by the compiler as
@synthesize propertyName = _propertyNameHowever, a few exceptions exist:
readwrite property with custom getter and setter
when providing botha getter and setter custom implementation, the property won't be automatically synthesized
readonly property with custom getter
when providing a custom getter implementation for a readonly property, this won't be automatically synthesized
@dynamic
when using
@dynamic propertyName, the property won't be automatically synthesized (pretty obvious, since@dynamicand@synthesizeare mutually exclusive)properties declared in a @protocol
when conforming to a protocol, any property the protocol defines won't be automatically synthesized
properties declared in a category
this is a case in which the
@synthesizedirective is not automatically inserted by the compiler, but this properties cannot be manually synthesized either. While categories can declare properties, they cannot be synthesized at all, since categories cannot create ivars. For the sake of completeness, I'll add that's it's still possible to fake the property synthesis using the Objective-C runtime.overridden properties(new since clang-600.0.51, shipping with Xcode 6, thanks Marc Schlüpmann)
when you override a property of a superclass, you must explicitly synthesize it
让我们停止谈论 Xcode。Xcode 是一个IDE。clang 是一个编译器。我们正在讨论的这个特性称为属性的自动合成,它是一种受 clang 支持的Objective-C 语言扩展,它是 Xcode 使用的默认编译器。
明确地说,如果您在 Xcode 中切换到 gcc,您将无法从该功能中受益(无论是 Xcode 版本)。同样,如果您使用文本编辑器并从命令行使用 clang 进行编译,您将将要。感谢自动合成,您不需要显式合成属性,因为它会被编译器自动合成为
@synthesize propertyName = _propertyName但是,存在一些例外情况:
具有自定义 getter 和 setter 的读写属性
当提供两个getter和setter定制实现,该属性将不会自动合成
带有自定义 getter 的只读属性
为只读属性提供自定义 getter 实现时,不会自动合成
@动态的
使用时
@dynamic propertyName,属性不会自动合成(很明显,因为@dynamic和@synthesize是互斥的)在@protocol 中声明的属性
符合协议时,协议定义的任何属性都不会自动合成
在类别中声明的属性
在这种情况下,
@synthesize编译器不会自动插入指令,但也不能手动合成此属性。虽然类别可以声明属性,但它们根本无法合成,因为类别不能创建 ivars。为了完整起见,我将补充说,仍然可以使用 Objective-C 运行时来伪造属性合成。覆盖的属性(自 clang-600.0.51 以来的新特性,随 Xcode 6 一起提供,感谢 Marc Schlüpmann)
当您覆盖超类的属性时,您必须显式合成它
It's worth noting that synthesizing a property automatically synthesize the backing ivar, so if the property synthesis is missing, the ivar will be missing too, unless explicitly declared.
值得注意的是,合成一个属性会自动合成支持的 ivar,所以如果缺少属性合成,除非明确声明,否则 ivar 也会丢失。
Except for the last three cases, the general philosophy is that whenever you manually specify all the information about a property (by implementing all the accessor methods or using @dynamic) the compiler will assume you want full control over the property and it will disable the autosynthesis on it.
除了最后三种情况外,一般的理念是,每当您手动指定有关属性的所有信息(通过实现所有访问器方法或使用@dynamic)时,编译器将假定您希望完全控制该属性,并且它将禁用它。
Apart from the cases that are listed above, the only other use of an explicit @synthesizewould be to specify a different ivar name. However conventions are important, so my advice is to always use the default naming.
除了上面列出的情况外,显式的唯一其他用途@synthesize是指定不同的 ivar 名称。但是约定很重要,所以我的建议是始终使用默认命名。
回答by KIDdAe
If you do not explicitly use @synthesizethe compiler will understand your property the same way if you had written
如果你没有明确地使用@synthesize编译器会像你写的一样理解你的属性
@synthesize undoManager=_undoManager;
then you will be able to write in your code things like :
那么你将能够在你的代码中编写如下内容:
[_undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter
This is the common convention.
这是普遍的约定。
if you write
如果你写
@synthesize undoManager;
you will have :
你将会有 :
[undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter
Personally I stop using @synthesize, since it's not mandatory any more.
For me the only reason to use @synthesizeis to link an iVarto a @property. If you want to generate specific getter and setter for it.
But in the given piece of code there is no iVar, I think that this @synthesizeis useless. But now I think the new question is "When to use iVar?", and I've no other response than "never" for this one !
我个人不再使用@synthesize,因为它不再是强制性的。对我来说,使用的唯一原因@synthesize是将 an 链接iVar到@property. 如果要为其生成特定的 getter 和 setter。但是在给定的一段代码中没有iVar,我认为这@synthesize是无用的。但是现在我认为新问题是“何时使用iVar?”,对于这个问题,除了“从不”之外,我没有其他回答!
回答by Steven Fisher
When should I add @synthesizeexplicitly to my code?
@synthesize我什么时候应该明确地添加到我的代码中?
Generally, if it's required: You will probably never hit a case where it's needed.
通常,如果需要:您可能永远不会遇到需要它的情况。
There's one case you might find it useful, though.
不过,有一种情况您可能会发现它很有用。
Say you're writing both a custom getter and setter, but want an instance variable to back it. (For an atomic property, this is as simple as wanting a custom setter: the compiler will write a getter if you specify a setter for a monatomic property, but not an atomic property.)
假设您正在编写自定义 getter 和 setter,但想要一个实例变量来支持它。(对于原子属性,这就像需要自定义 setter 一样简单:如果您为单原子属性指定了 setter,而不是原子属性,编译器将编写一个 getter。)
Consider this:
考虑一下:
@interface MyObject:NSObject
@property (copy) NSString *title;
@end
@implementation MyObject
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
This will not work, because _titledoesn't exist. You've specified both a getter or setter, so Xcode (correctly) doesn't create a backing instance variable for it.
这将不起作用,因为_title不存在。您已经指定了 getter 或 setter,因此 Xcode(正确地)不会为其创建支持实例变量。


You have two choices for making it exist. You can either change the @implementationto this:
你有两个选择让它存在。您可以将其更改@implementation为:
@implementation MyObject {
NSString *_title;
}
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
Or change it to this:
或者改成这样:
@implementation MyObject
@synthesize title = _title;
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
In other words, although synthesize is for practical purposes never necessary*, it can be used to defineproperty-backing instance variables when you're providing a getter/setter. You can decide which form here you want to use.
换句话说,虽然综合出于实际目的从来没有必要*,但当您提供 getter/setter 时,它可用于定义支持属性的实例变量。您可以在此处决定要使用的表格。
In the past, I've favoured specifying the instance variable in the @implementation {}, but I now think the @synthesizeroute is a better choice as it removes the redundant type and explicitly ties the backing variable to the property:
在过去,我已经看好指定的实例变量@implementation {},但我认为现在的@synthesize路线是一个更好的选择,因为它消除冗余类型,并明确绑后盾变量属性:
- Change the property's type, and the instance variable's type changes.
- Change its storage qualifier (for instance, make it weak instead of strong or strong instead of weak) and the storage qualifier changes.
- Remove or rename the property, and the
@synthesizewill generate a compiler error. You won't end up with stray instance variables.
- 改变属性的类型,实例变量的类型就会改变。
- 更改其存储限定符(例如,将其设为弱而不是强或将其设为强而不是弱)并且存储限定符会发生变化。
- 删除或重命名属性,
@synthesize将生成编译器错误。您最终不会得到杂散的实例变量。
*-I know one case where it was necessary, relating to splitting functionality across categories in multiple files. And I wouldn't be surprised if Apple fixes this, or even already has.
*-我知道一种必要的情况,涉及在多个文件中跨类别拆分功能。如果 Apple 修复了这个问题,甚至已经修复了,我也不会感到惊讶。
回答by Fogmeister
OK, when you create a property...
好的,当您创建属性时...
@property NSString *name;
Xcode will auto synthesise an iVar as if you had written...
Xcode 会自动合成一个 iVar,就像你已经写过一样......
@synthesize name = _name;
This means you can access the property with...
这意味着您可以使用...
self.name;
// or
_name;
Either will work but only self.nameactually uses the accessor methods.
self.name两者都可以工作,但仅实际使用访问器方法。
There is only one time that auto synthesise does not work: If you overwrite but the setter AND the getter method then you will need to synthesise the iVar.
只有一次自动合成不起作用:如果你覆盖了 setter 和 getter 方法,那么你将需要合成 iVar。
You are fine if you just override the setter or if you just override the getter. But if you do both then the compiler won't understand it and you will need to synthesise it manually.
如果你只是覆盖 setter 或者你只是覆盖 getter,你就可以了。但是如果你两者都做,那么编译器就不会理解它,你需要手动合成它。
As a rule of thumb though.
不过,根据经验。
Don't make iVars. Just use the property. Don't synthesise it.
不要制作 iVar。只需使用该属性。不要合成它。
回答by Leo Natan
Property synthesis is required when a property is declared in a protocol. It will not be automatically synthesized in an implementing interface.
在协议中声明属性时需要进行属性合成。它不会在实现接口中自动合成。
回答by Harry McGovern
Thanks for clarifying that. I had a similar problem.
感谢您澄清这一点。我有一个类似的问题。
@synthesize firstAsset, secondAsset, audioAsset;
@synthesize activityView;
So now, having commented them out, I went through and replaced each occurrence with, for example
所以现在,在将它们注释掉之后,我经历并替换了每个事件,例如
self.firstAsset It seems I could also use firstAsset, but I find I miss seeing the "" too often.
self.firstAsset 似乎我也可以使用firstAsset,但我发现我太想念“”了。
回答by Sam Fischer
Xcode doesn't require an explicit @synthesizedeclaration.
Xcode 不需要显式@synthesize声明。
If you don't write @synthesizeits the same as doing :
如果你不写@synthesize它和做一样:
@synthesize manager = _manager;
The sample code might've been old. They'll update it soon.
示例代码可能已经过时了。他们很快就会更新它。
You can access your properties like :
您可以访问您的属性,例如:
[self.manager function];
This is Apple's recommended convention. I follow it, and I recommend that you do too!
这是 Apple 推荐的约定。我遵循它,我建议你也这样做!

