1

このような問題については、書籍、記事などのさまざまな情報源で読んだことがありますが、その考えを理解できません。バックアップされた i-vars とプロパティの問題が発生したときの例と、その解決方法を教えてください。そして、ここhttp://blog.bignerdranch.com/463-a-motivation-for-ivar-decorationsから次のコードを読みました。

@property (copy) NSString *name;
...
@synthesize name;
...
- (void) setPonyInfoFromPropertyDict: (NSDictionary *) ponyProperties {
    NSString *name = [ponyProperties objectForKey: @"Name"];
    ponyName = name; //self.ponyName=name should solve the problem? 
}

NSMutableString *mutableName = [NSMutableString stringWithString: @"Mikey"];
NSDictionary *ponyProperties = [NSDictionary dictionaryWithObject: mutableName  
                               forKey: @"Name"];
[pony setPonyInfoFromPropertyDict: ponyProperties];
[mutableName setString: @"Wookiee"]; 

そのコードと記事はこの問題に関連していますか? 正しい方法は、self.ponyName=name? を使用することです。他の設定方法では?

4

1 に答える 1

1

この例は間違っているか、不適切だと思います。適切な例は

@property (copy) NSString *ponyName; // not name!
...

@synthesize ponyName; // not name!
...
- (void) setPonyInfoFromPropertyDict: (NSDictionary *) ponyProperties {
    NSString *name = [ponyProperties objectForKey: @"Name"];
    ponyName = name;
    //self.ponyName = name; // will solve the problem 
}

name変更可能な文字列になる可能性があるため、割り当てられた後に変更されないようにしたい場合は、コピーする必要があります。copyタスクにプロパティを使用できますが、

ponyName = name;

セッターをまったく使用していません。

self.ponyName = name;

問題を修正nameし、セッターによってコピーされます。


討論

Objective-C でプログラミングする際の最も一般的な間違いの 1 つは、setter/getter を使用する代わりに ivar に直接アクセスすることです。

アクセサリ メソッドは通常、ivar にアクセスして設定するための多くのロジックを提供するため、特にメモリ管理に関して重要です。現在、それらの実装は ARC コンパイラによって大幅に簡素化されていますが、MRC を使用する場合、release/retainバランスを処理するのに役立つアクセサリ メソッドが重要です。

ARC の下でも有効な例は、copyプロパティを宣言する場合です。そのような場合、合成されたセッターは ivar に代入する前に引数をコピーします。

[self setMyCopyProperty:aNewThing];

または同等に

self.myCopyProperty = aNewThing;

aNewThingcopyバッキングされたivarに割り当てられる前に、メッセージを受け取ります。

一方、このようにプロパティを合成すると

@synthesize myCopyProperty;

あなたは偶然に自分がやっていることに気付くかもしれません

myCopyProperty = aNewThing;

aNewThingivar に直接アクセスしているため、これはコピーされません。

ivar とアクセサリ メソッドを混同しないようにするために、ivar の前にアンダースコアを付けることが標準的な規則になりました。つまり、次のように合成します。

@synthesize myCopyProperty = _myCopyProperty;

このように、うっかりしてしまうと

myCopyProperty = aNewThing;

myCopyPropertyivarのようなものがないため、コンパイルされません。おそらく、メモリ関連の問題をデバッグしているときにひどい頭痛から解放されます。init代わりに、自分が何をしているのかを知っていて、(おそらくメソッドで) ivar に本当にアクセスしたい場合は、単純に行うことができます。

_myCopyProperty = [aNewThing copy];

これは、セッターを使用しないという意図をより明確に示しています。

最後に、最新バージョンのclangコンパイラでは、次@synthesizeの形式で自動的に挿入されるため、明示的なものを避けることができることに注意してください。

@synthesize foo = _foo;

いくつかの例外が適用されます。詳細については、次を参照してください: @synthesize を明示的に使用する必要があるのはいつですか?

于 2013-11-14T16:24:55.523 に答える