2011-07-28 8 views
4

私は奇妙な__blockストレージ変数クラッシュ

NSArray *array = [NSArray arrayWithObjects:@"1", @"2", @"3", nil]; 

__block NSString *a = @"-1"; 

[array enumerateObjectsUsingBlock:^(id whoCares, NSUInteger idx, BOOL *stop) { 
    a = [NSString stringWithFormat:@"%@ %d", a, idx]; 
    NSLog(@"%@", a); 
}]; 

NSLog(@"%@", a); 
は、このコードが動作する

次(愚かな)例まで蒸留してきた私のコードに問題がありますが、私は、ブロック内の最初のNSLogを(コメントアウト場合)コードがクラッシュします。私は、次の

a = [NSString stringWithFormat:@"%d", idx]; 

にフォーマット文字列を変更した場合でも、その後、コードはブロック内のNSLogせずに細かい動作します。

ここでは何が起こっていますか?私は何かを誤解していることを願っています。

+0

これはすべてコードですか? –

+1

また、あなたが見ている特定のクラッシュは何ですか? –

+0

これは、私が実際にやっていることの例です。私はブロックで列挙する配列を持っており、変数をその変数から派生した値で再割り当てします。これは、最後のNSLogでの不正なアクセスエラーでした。 –

答えて

2

stringWithFormat:は、あなたが保持していない自動リリースオブジェクトを提供します。ブロックが終了し、NSLogに電話すると、aはすでに割り当てが解除されている可能性があります。

解決策の1つは、変更可能な文字列を使用して、再割り当てする代わりに毎回追加することです。

NSArray *array = [NSArray arrayWithObjects:@"1", @"2", @"3", nil]; 

NSMutableString *a = [NSMutableString stringWithFormat:@"-1"]; 

[array enumerateObjectsUsingBlock:^(id whoCares, NSUInteger idx, BOOL *stop) { 
    [a appendFormat:@" %d", idx]; 
}]; 

NSLog(@"%@", a); 
+0

私は今ブロックが自分のスコープを持っていると考えるのではなく、ありがたく思っています。とにかくうまくいく、変更可能なデータ構造を使用するようにソリューションを移動しました。私はまだ何が起きているのか不思議でした。最初のNSLogがクラッシュを防ぐのは私を混乱させていましたが、今は意味があります。おかげで –

+1

ほぼ正しい; NSMutableStringを使用している場合は '__block'は必要ありません。 NSLog()がクラッシュを防ぐのは完全に偶然であり、そうでない場合は動作が定義されていないため意味がありません。 :) – bbum

+0

@bbumかなり正しいですが、__blockを編集して、訂正してくれてありがとう! – zpasternack