10

Objective-Cでインスタンス変数にアクセスするための適切な構文は何ですか?

次の変数があるとします。

@interface thisInterface : UIViewController {
    NSMutableString *aString;
}

@property (nonatomic, retain) NSMutableString *aString;

そしてそれが合成されていること。

アクセスしたいときは、まず割り当てて初期化します。Objective-C でプログラミングしてから約 1 か月が経ちましたが、2 つの異なる形式の構文を見てきました。私はaString = [[NSMutableString alloc] initWithString:@"hi"]、人々が単に文字列をそのように割り当てるのを見てきました。self.aStringまた、ivar で開始してから、ivar の初期化に進む人も見てきました。インスタンス変数を初期化する最も適切な方法は何かを理解しようとしているだけだと思います。前の例では、そこから EXC_BAD_ACCESS エラーを受け取ったからです。しかし、前に追加した後self.、表示されませんでした。

これが重複した質問である場合は申し訳ありませんが、SOに関するいくつかの投稿を読んだ後、興味をそそられました。ずさんなよりも適切であることを好むので、Objective-C で適切な構文を学ぼうとしています。

4

7 に答える 7

15

プロパティと@synthesize.m ファイルを宣言した場合は、次のように設定するだけです。

self.aString = @"hi"; // or [[NSMutableString alloc] initWithString:@"hi"];

Usingself.varNameは、プロパティ宣言が実際に行うことを利用します。新しい値の保持 (プロパティにはretain属性があるため)、古い値の解放などを処理します。

あなただけの場合:

aString = someValue;

... にあった元の値をリークしている可能性があります。aString使用しself.aStringないと、変数に直接アクセスするのではなく、プロパティを介してアクセスするからです。

于 2011-06-15T15:30:57.423 に答える
12

との違いに注意してself->varNameくださいself.varName

1つ目はポインタアクセスです。2つ目は、プロパティへのアクセスです。

なぜそれが重要なのですか?ポインタへのアクセスは直接です。一方、プロパティアクセスでは、ゲッターとセッターを使用します(それらが存在する@synthesizedかどうかは関係ありません)。さらに、便宜上、@ synthesizedアクセサーがメモリ管理を処理します(つまり、を使用する場合self.varName = ...;)が、それvarName = ...;が言うこと、つまり割り当て->(取得する可能性のあるEXC_BAD_ACCESSエラーの説明があります)のみを実行します。

構文的には、どちらの形式も正しいです。意図をよりよく伝えたい場合self->varNameは、ポインタを直接操作したいときに使用しself.varName、便利さを利用したいときに使用します@property

于 2011-06-15T15:46:15.603 に答える
7

可能なすべての組み合わせは次のとおりです(私は思います)OKとBADは、aStringプロパティにretain属性がある場合にのみ正しいです。

@property (nonatomic, retain) NSMutableString *aString;

それで:

1

aString = [[NSMutableString alloc] init]; //OK: 

これは問題ありませんが、aStringが無効なオブジェクトを指していない場合、またはそのオブジェクトへの参照を失い、オブジェクトに到達して解放できないためにリークする場合に限ります。

2

aString = [NSMutableString string]; //BAD

(そのように宣言したように)aStringを保持することになっているので、悪いです。保持しておらず、将来確実にEXC_BAD_ACCESSを取得します。

3

aString = [[NSMutableString string] retain]; //OK

最初のアプローチと同じですが、aStringが有効なオブジェクトを指していない場合にのみ有効です。ただし、最初のものを使用します。

4

aString = [[[NSMutableString alloc] init] autorelease];//BAD

2番目のアプローチと同じです。

5

self.aString = [[NSMutableString alloc] init]; //BAD!!

2回保持しているため、メモリリークが発生する可能性があります。

6

self.aString = [[NSMutableString string]; //******GOOD!******

これはおそらく最も安全です。これはプロパティセッターによって保持され、セッターを使用しているため、aStringによってポイントされた可能性のある他のオブジェクトは適切に解放されます。

7

self.aString = [[NSMutableString string] retain]; //BAD

これは2回保持されます。

8

self.aString = [[[NSMutableString alloc] init] autorelease];//Ok

これもOKですが、この長いアプローチの代わりに便利な方法を使用します:)

自分が何をしているのかを知っている場合は、#1と#3のオプションが完全に優れていることに注意してください。実際、私はそれらを#6よりもはるかに頻繁に使用しています

于 2011-06-15T15:34:40.097 に答える
2

self.私は個人的に構文を使用することを好みます。NSAutoreleasePool がドレインされたときに失われる現在のスコープ内の他の変数だけでなく、インスタンス変数であることを簡単に判断できるようになります。ただし、両方の方法で使用するのが正しいです。EXC_BAD_ACCESS エラーが発生した場合、それは を使用せずにアクセスしたからではありませんself.。それを割り当てる必要があると言っているのは正しいです。変数にアクセスするためにどの方法を選択しても、一貫性を保つか、エラーが発生します。

これが役立つことを願っています。

于 2011-06-15T15:30:32.120 に答える
2

initdeallocおよびアクセサー自体を除いて、常にアクセサーを使用します。これを行うと、あなたが説明しているような頭痛の種を大幅に節約できます。また、ivar にプロパティとは異なる名前を付けてください ( _foofoo_mFooではありませんfoo)。

self.fooとまったく同じ[self foo]です。メソッドを呼び出しますfooself.foo = xはまったく同じ a[self setFoo:x]です。メソッドを呼び出しますsetFoo:fooプロパティを変数として合成した場合retain、これは次のようになります。

@synthesize foo = foo_;

- (void)setFoo:(id)value {
  [value retain];
  [foo_ release];
  foo_ = value;
}

これにより、 の古い値が正しく解放されfoo_、新しい値が割り当てられて保持されます。

foo = x( fooivar であると仮定) は、メソッドを呼び出しません。なし。xポインタ inにポインタ in の値を代入するだけfooです。foo保持されたものを指している場合、それは漏洩しています。割り当てている新しい値が保持されていないと、後でクラッシュします。

これに対する解決策は、可能な場合は常にアクセサーを使用することです。

于 2011-06-15T15:38:51.220 に答える
1

また。

ドット構文を使用すると、(一部の人にとっては)よりクリーンになり、同等のものにコンパイルされます。すなわちself.iVar、と同じで[self iVar]ありself.iVar = aValue、と同じです[self setIVar:aValue];

于 2011-06-15T15:26:04.963 に答える
0

self.aStringのシンタックスシュガー[self aString]です。プロパティを合成するには、-aStringand-setAString:メソッドを作成するだけです(選択したプロパティに応じて、些細な影響ではありません)。

ここで問題は、.表記を使用するかどうかです。使用しないことをお勧めします。なんで?まず、Objective-CがCへの単なる追加を目指していることを知ってください。これは、すべての有効なCコードが有効なObjective-Cコードでもあることを意味します。

次に、ドット表記で何をしたかを見てみましょう。最後のステートメントはもう成り立たない。C構造体のフィールドへのアクセスとObjective-Cメソッドの送信を区別することはできません。

したがって、ドット表記は使用しないでください。[自己..]を使用することをお勧めします。

于 2011-06-15T15:45:32.343 に答える