私の知る限り、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;
今戸惑っています...いつ追加する必要がありますか@synthesize
私のコードに明示的に?
たくさんの答えがありますが、大きな混乱もあります。私はいくつかの注文をしようとします(または混乱を増やす、私たちが見るでしょう...)
Xcodeの話をやめましょう。 Xcodeは[〜#〜] ide [〜#〜]です。 clangはcompilerです。私たちが議論しているこの機能は、プロパティの自動合成と呼ばれ、それは clangでサポートされているObjective-C言語拡張機能 です。これはXcodeで使用されるデフォルトのコンパイラです。
明確にするために、Xcodeでgccに切り替えると、(Xcodeバージョンに関係なく)この機能のメリットは得られません。同様に、テキストエディターを使用し、clangを使用してコンパイルする場合コマンドライン、あなたがします。
自動合成のおかげで、プロパティはコンパイラによって自動的に合成されるため、明示的にプロパティを合成する必要はありません。
@synthesize propertyName = _propertyName
ただし、いくつかの例外があります。
カスタムgetterおよびsetterを使用したreadwriteプロパティ
both両方のゲッターとセッターのカスタム実装を提供する場合、プロパティは自動的に合成されません
カスタムゲッター付きの読み取り専用プロパティ
読み取り専用プロパティにカスタムゲッター実装を提供する場合、これは自動的に合成されません
@ dynamic
@dynamic propertyName
を使用する場合、プロパティは自動的に合成されません(@dynamic
と@synthesize
は相互に排他的であるため、かなり明白です)
@ protocolで宣言されたプロパティ
プロトコルに準拠する場合、プロトコルが定義するプロパティは自動的に合成されません。
カテゴリで宣言されたプロパティ
これは、@synthesize
ディレクティブがコンパイラによって自動的に挿入されない場合ですが、このプロパティも手動で合成することはできません。カテゴリはプロパティを宣言できますが、カテゴリはivarを作成できないため、プロパティをまったく合成できません。完全を期すために、まだ可能だと付け加えます Objective-Cランタイムを使用してプロパティ合成を偽造するため 。
オーバーライドされたプロパティ(clang-600.0.51以降の新機能、Xcode 6に付属、MarcSchlüpmannに感謝)
スーパークラスのプロパティをオーバーライドする場合、明示的に合成する必要があります
プロパティを合成すると、バッキングivarが自動的に合成されるため、プロパティの合成が欠落している場合、明示的に宣言されていない限り、ivarも欠落することに注意してください。
最後の3つのケースを除いて、一般的な哲学は、プロパティに関するすべての情報を手動で指定するときはいつでも(すべてのアクセサメソッドを実装するか、@dynamic
を使用して)、プロパティと自動合成を無効にします。
上記の場合とは別に、明示的な@synthesize
を使用する他の唯一の方法は、異なるivar名を指定することです。ただし、規則は重要であるため、私のアドバイスは常にデフォルトの命名を使用することです。
明示的に@synthesize
を使用しない場合、コンパイラは、記述した場合と同じ方法でプロパティを理解します
@synthesize undoManager=_undoManager;
次のようなコードを記述できるようになります。
[_undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter
これは一般的な規則です。
書いたら
@synthesize undoManager;
あなたが持っています:
[undoManager doSomething]; // iVar
[self.undoManager doSomethingElse]; // Use generated getter
個人的には@synthesize
の使用をやめました。これはもう必須ではないからです。私にとって@synthesize
を使用する唯一の理由は、iVar
を@property
にリンクすることです。特定のゲッターとセッターを生成する場合。しかし、指定されたコードにはiVar
がありません。この@synthesize
は役に立たないと思います。しかし、今では新しい質問は「いつiVar
を使用するか?」であり、この質問に対して「決して」以外の応答はありません。
いつ@synthesize
をコードに明示的に追加すべきですか?
通常、必要な場合:必要な場合はおそらくヒットしません。
ただし、役に立つ場合が1つあります。
カスタムgetterとsetterの両方を書いているが、それを裏付けるインスタンス変数が必要だとします。 (アトミックプロパティの場合、これはカスタムセッターを必要とするのと同じくらい簡単です。アトミックプロパティではなく単原子プロパティのセッターを指定すると、コンパイラはゲッターを書き込みます。)
このことを考慮:
@interface MyObject:NSObject
@property (copy) NSString *title;
@end
@implementation MyObject
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
_title
が存在しないため、これは機能しません。ゲッターまたはセッターの両方を指定しているため、Xcodeは(正しく)バッキングインスタンス変数を作成しません。
存在させるには2つの選択肢があります。 @implementation
を次のように変更できます。
@implementation MyObject {
NSString *_title;
}
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
または、これに変更します:
@implementation MyObject
@synthesize title = _title;
- (NSString *)title {
return _title;
}
- (void)setTitle:(NSString *)title {
_title = [title copy];
}
@end
言い換えると、合成は実用的な目的のために決して必要ではありません*が、ゲッター/セッターを提供しているときにdefine property-backingインスタンス変数に使用できます。ここで使用するフォームを決定できます。
以前は、@implementation {}
でインスタンス変数を指定することを好みましたが、冗長な型を削除し、バッキング変数をプロパティに明示的に結び付けるので、@synthesize
ルートがより良い選択だと思います:
@synthesize
はコンパイラエラーを生成します。迷子のインスタンス変数で終わることはありません。*-複数のファイルのカテゴリ間で機能を分割することに関連して、必要なケースを1つ知っています。そして、Appleがこれを修正するか、すでに持っていたとしても、驚かないでしょう。
OK、プロパティを作成するとき...
@property NSString *name;
Xcodeは、あなたが書いたようにiVarを自動合成します...
@synthesize name = _name;
これは、プロパティにアクセスできることを意味します...
self.name;
// or
_name;
どちらでも機能しますが、self.name
は実際にアクセサメソッドを使用します。
自動合成が機能しないのは一度だけです:セッターとゲッターメソッドを上書きする場合、iVarを合成する必要があります。
セッターをオーバーライドするだけでも、ゲッターをオーバーライドするだけでも大丈夫です。しかし、両方を行うと、コンパイラはそれを理解できず、手動で合成する必要があります。
経験則として。
IVarsを作成しないでください。プロパティを使用するだけです。合成しないでください。
プロトコルでプロパティが宣言されている場合、プロパティ合成が必要です。実装インターフェイスでは自動的に合成されません。
それを明確にしてくれてありがとう。同様の問題がありました。
@synthesize firstAsset, secondAsset, audioAsset;
@synthesize activityView;
だから今、それらをコメントアウトして、私は通り抜けて、例えば
self.firstAsset firstAssetを使用することもできますが、 ""が頻繁に表示されないことがあります。