0

次の変数を定義しています。

@property (nonatomic, retain) NSMutableArray *arraySpeechSentences;

そして、私は次の方法でそれを初期化しようとしています:

// Set the array of sentences to the stored array
NSMutableArray *speechSentences = [[NSMutableArray alloc] initWithArray:[tempDict objectForKey:key]];
arraySpeechSentences = speechSentences;
[speechSentences release];

[arraySpeechSentences count] を呼び出そうとすると、アプリケーションがクラッシュします。ただし、次の方法で変数を設定すると:

// Set the array of sentences to the stored array
NSMutableArray *speechSentences = [[NSMutableArray alloc] initWithArray:[tempDict objectForKey:key]];
self.arraySpeechSentences = speechSentences;
[speechSentences release];

[arraySpeechSentences count] を完全に問題なく呼び出すことができます。セルフを使えばという印象でした。変数がすでに設定されているかどうかを確認するだけで、設定されている場合は、新しい値を割り当てる前にオブジェクトを解放します。私はこれを間違えましたか? もしそうなら、いつ自分自身を使うべきですか? 値を設定するには?

助けてくれてありがとう、エリオット

4

3 に答える 3

7

セッター (self.foo = ...またはなど[self setFoo:...]) を使用すると、古い値が解放されますが、指定した例で必要な新しい値も保持されます。

問題は、配列を割り当てて初期化してから解放していることです。これは、もう必要ないことを示しています。そのため、setter を使用するか (通常は望ましい)、配列を解放しないでください。

于 2012-07-12T14:50:17.497 に答える
3

ARC を使用していない場合は、次のように入力する必要があります。

arraySpeechSentences = [speechSentences retain];

インスタンス変数に直接アクセスしているため、インスタンス変数の値は、リリースしたばかりarraySpeechSentencesのオブジェクトのアドレスになるため、無効なポインターです。speechSentenceプロパティで宣言したセマンティックは、インスタンス変数自体には影響しません。

と入力するとself.arraySpeechSentences、実際には setter のショートカットが使用され、パラメーターとして渡された値が[self setArraySpeechSentences:speechSentences]実際に保持retainされます (プロパティを合成した場合は、プロパティ宣言で指定したため保持されます。アクセサーを自分で記述した場合は、価値を確実に保持するためのあなたの仕事)。

于 2012-07-12T15:00:44.220 に答える
2

私はこれについて詳細な答えを出そうとします。

まず、@property/@synthesizeディレクティブを使用するときは、変数の周りにゲッター メソッドとセッター メソッドを作成します。

あなたの場合、変数が呼び出されarraySpeechSentences(コンパイラが変数を作成します)、これらのメソッド(セッターとゲッター)にself..

self.arraySpeechSentences = // something 

と同じです

[self setArraySpeechSentences:something]; // setter

NSMutableArray* something = self.arraySpeechSentences;

に等しい

NSMutableArray* something = [self arraySpeechSentences]; // getter

コードの最初のスニペットで

NSMutableArray *speechSentences = [[NSMutableArray alloc] initWithArray:[tempDict objectForKey:key]];
arraySpeechSentences = speechSentences;

arraySpeechSentences同じオブジェクトspeechSentencesを指します。しかし、[speechSentences release]そのオブジェクトのロックを解除するとarraySpeechSentences、ダングリング ポインターになります。私が推測する割り当て解除されたインスタンスに送信されたメッセージを受け取ります。ゾンビに見えるようにしてみてください。

保持カウントに関して言えば、配列の保持カウントは 1 ですalloc-init。しかし、releaseそれを行うと、保持カウントがゼロになり、オブジェクトが存在しなくなり、アクセスしようとするとクラッシュしますarraySpeechSentences

代わりに、プロパティを扱うときは、変数に適用されるポリシーが重要です。プロパティはretainポリシーを使用するため、オブジェクトを設定すると

self.arraySpeechSentences = // something

参照されたオブジェクトの保持カウントが増加します。ボンネットの下では、言うことself.arraySpeechSentences = // somethingはセッターを呼び出すことと同じです

- (void)setArraySpeechSentences:(NSMutableArray*)newValue
{
    // pseudo code here...
    if(newValue != arraySpeechSentences) {

       [arraySpeechSentences release];
       arraySpeechSentences = [newValue retain]; 
    }
}

2 番目のスニペットは、オブジェクトの保持カウントが実行時に 1 でありalloc-init、呼び出すself.arraySpeechSentences =と 2 になり、解放すると 1 に戻るため、機能します。今回は、オブジェクトの保持カウントが 1 であるため、オブジェクトは存続します。

retainまたはポリシーを持つプロパティがある場合は、同様にcopyオブジェクトを解放することを忘れないでくださいdealloc。そうしないと、リークが発生する可能性があります。

- (void)dealloc
{
    [arraySpeechSentences release];
    [super dealloc];
}

メモリの仕組みを理解するには、MemoryManagement Apple docを読むことをお勧めします。

PS iOS 5 以降、ARC (自動参照カウント) と呼ばれる新しいコンパイラ機能があり、呼び出しを忘れることができますretain/release。また、オブジェクトグラフの観点から考える必要があるため、検討することをお勧めします。

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

于 2012-07-12T15:14:46.273 に答える