3

こんにちは、.h ファイルにプロパティがあるとします。

@property (nonatomic) NSString * myText;
@property (nonatomic) SomeClass * someObj;

さて、クラスの実装です。

たとえば、合成を使用することを忘れていなかったので、次のように呼び出しました。

@synthesize myText, someObj;

ここで、プロパティ名の前に置くのを忘れたコードで言いますself(そしてivarを直接参照します):

myText = @"Hello";
someObj = [[SomeClass alloc] init];

私の質問は: これは問題ですか? どのような問題が発生する可能性がありますか? それとも大したことない?

ps。ARC を使用しているとします。

4

5 に答える 5

2

私の質問は: これは問題ですか?

これは「ivar への直接アクセス」と呼ばれます。場合によっては、それは問題ではありませんが、必要です。self初期化子、dealloc、およびアクセサー (セッター/ゲッター) は、の ivar に直接アクセスする必要がある場所です。他のほとんどの場合、アクセサーを優先します。

以外のインスタンスの ivar に直接アクセスするselfことは避けるべきです。ここでの簡単な問題は、C 構造体のように、無効なアドレス (未定義の動作) で読み取りまたは書き込みを行う可能性があることです。メッセージ化されたオブジェクトが の場合、nilそのメッセージの実装は実行されません。

どのような問題が発生する可能性がありますか?

最大の 2 つ:

  • これらの変更に関する KVO 通知は届きません
  • そして、通常、正しいセマンティクスを提供する実装をバイパスしています (正当化できます)。この場合のセマンティクスは、メモリ管理、コピー、同期、または状態変化のその他の結果と同等である可能性があります。たとえば、セッターがオーバーライドされた場合、そのセッターのサブクラスのオーバーライドをバイパスしているため、オブジェクトが一貫性のない状態のままになる可能性があります。

参照:なぜ ivar を使用するのですか?

于 2013-09-01T19:51:08.720 に答える
1

基礎となるインスタンス変数に誤ってアクセスしないでください。そうする予定がある場合に限ります。

予期しない副作用として、KVO が機能しない、オーバーライドするアクセサー メソッドが呼び出されない、属性copyatomic属性が無効になる、などがあります。

@synthesize Xcode 4.4 以降を使用する必要はありません。デフォルトの合成を使用する場合、コンパイラは同等の処理を行います

@synthesize myText = _myText;

となることによって

_myText = @"Hello";
self->_myText = @"Hello";

は同等でありmyText = @"Hello";、「未定義の識別子」コンパイラ エラーが発生します。

コンパイラだけを使用する場合@synthesize myText(下位互換性のため):

@synthesize myText = myText;

これはエラーが発生しやすいです。

アクセサの代わりに基礎となるインスタンス変数を使用する正当な理由があることに注意してください- しかし、偶然にこれを行うのは悪いスタイルです。

于 2013-09-03T01:30:41.857 に答える
0

30 年間、推奨される方法は次のとおりです。

  • getter/setter メソッドまたは new.演算子を使用して ivar を読み書きします。
  • 必要な場合にのみ ivar に直接アクセスしてください。
  • ivar が常に直接アクセスされる場合を除き、誤って使用しないように ivar 名を選択します (そのため、ivar の前にアンダースコアを付けるのがデフォルトの動作と規則です)。

いくつかの状況で ivar に直接アクセスする必要があります。

  • 手動のメモリ管理にはそれが必要です。ARC が有効な場合、これは必要ありません。
  • 変数 variable を何百万回も連続して読み取るつもりで、何らかの理由でそれを一時変数に割り当てることができない場合。
  • 低レベルの C API を使用している場合、おそらく ivar へのポインターが必要です。たとえば、Apple のlibxml2 サンプル コードは ivar に直接アクセスします。
  • デフォルトの @synthesize 実装を使用する代わりに、getter メソッドまたは setter メソッドを自分で記述している場合。私は個人的にこれを常に行っています。

これらの状況 (および他のいくつかの状況) を除いて、ivar に直接アクセスしないでください。また、すべての ivar の前にアンダースコアを付けて、誤ってアクセスしないようにし、コーディング中に xcode のオートコンプリート/インテリセンスに表示されないようにします。

規約の主な理由は次の 2 つです。

  • クラスの基になるメモリ構造が変更されても、ゲッター/セッター メソッドとプロパティを保持できます。ivar の名前を変更すると、ivar を読み取るすべてのコードが破損するため、ivar に直接アクセスするコードをゼロにするか、ほとんどコードを持たないようにすることをお勧めします。
  • サブクラスはゲッターとセッターをオーバーライドできます。ivar をオーバーライドすることはできません。一部の人々は、サブクラスが getter と setter をオーバーライドすることを許可されるべきではないと考えています - これらの人々は間違っています。オーバーライドできることは、サブクラスを作成する全体のポイントです。
  • ivar に直接アクセスすると、KVC や KVO などの基本的な機能が機能しなくなる可能性があります。

もちろん、やりたいことは何でもできます。しかし、コンベンションは何十年も前から存在しており、機能しています。それに従わない理由はありません。

于 2013-09-08T09:52:16.287 に答える