3

Objective-Cで^blocksを使用するといくつかの問題が発生しました。ブロック内からインスタンス変数を設定しようとしています-このトピックに関するいくつかのAppleのドキュメントを読みましたが、すべてを試したと感じています。

@interface MyClass
{
    // I have tried all possible combinations using __weak, __strong and __block.
    __weak __block NSMutableArray *filenames;
}

// *.m
static ASIFormDataRequest *g_request = nil;

@implementation MyClass
-(void) funnymethod
{
    filenames = [NSMutableArray array];
    [filenames addObject:@"This is a string."];
    NSLog(@"%@", filenames);

    g_request = [InitializerClass initializeRequest];
    [g_request setCompletionBlock:^
    {
        filenames = [NSMutableArray array];
        [filenames addObject:@"This is another string."];
        NSLog(@"%@", filenames);
    }];

    [g_object startASynchronous];
}
@end

上記のコードは次の出力を提供します:("これは文字列です。")(null)

それは最悪だ。だから、私は__weak、__ strong、__ blockのさまざまな組み合わせを試しましたが、それ以外の場合は次の出力が得られます:( "これは文字列です。")( "これは別の文字列です。")しかし!大規模ですが。完了ブロックが終了することはありません。接続が開いていることを示すトップバーのアクティビティインジケータが回転し続け、画面が応答しなくなります。

ブロック内からfilenames-objectを正常に設定するにはどうすればよいですか?前もって感謝します。

4

1 に答える 1

4

修飾子の機能:

__blockこの修飾子を使用すると、クロージャで指定された変数に格納されている値を変更できます。

__weakオブジェクトの割り当て解除を妨げないオブジェクトへの参照です。

__strongオブジェクトの割り当て解除を妨げるオブジェクトへの参照です。

するべきこと:

__weak現在のスコープが終了した後に配列の割り当てが解除されるのを妨げないため、必要な処理を実行しません。非同期呼び出しを行っているため、ブロックが実行される前に、ランタイムが配列によって使用されているメモリを再利用することを妨げるものは何もありません。

__strong現在のスコープの終わりを超えてオブジェクトを保持します。これはあなたが望むものです。

__blockブロックで指定された変数を変更できますが、インスタンス変数を参照する場合selfは自動的に保持されるため、これは必要ありません。

参照カウント環境では、デフォルトで、ブロック内のObjective-Cオブジェクトを参照すると、そのオブジェクトが保持されます。これは、オブジェクトのインスタンス変数を単に参照する場合でも当てはまります。ただし、__blockストレージタイプ修飾子でマークされたオブジェクト変数は保持されません。

注:ガベージコレクション環境では、変数に__weak修飾子と__block修飾子の両方を適用すると、ブロックはそれが存続することを保証しません。メソッドの実装内でブロックを使用する場合、オブジェクトインスタンス変数のメモリ管理のルールはより微妙です。

参照によってインスタンス変数にアクセスする場合、selfは保持されます。

私はあなたの問題がここにあると思います(太字の関連部分):

__blockストレージタイプ修飾子を適用することにより、インポートされた変数が変更可能(つまり、読み取り/書き込み)になるように指定できます。__blockストレージは、ローカル変数のレジスタ、自動、および静的ストレージタイプに似ていますが、相互に排他的です。

__block変数は、変数の字句スコープと、変数の字句スコープ内で宣言または作成されたすべてのブロックおよびブロックコピーの間で共有されるストレージに存在します。したがって、フレーム内で宣言されたブロックのコピーがフレームの終わりを超えて存続する場合(たとえば、後で実行するためにどこかにキューに入れられることによって)、ストレージはスタックフレームの破棄に耐えます。特定の字句スコープ内の複数のブロックは、共有変数を同時に使用できます。

最適化として、ブロックストレージは、ブロック自体と同じように、スタックから始まります。Block_copyを使用して(またはブロックがコピーを送信されるときにObjective-Cで)ブロックがコピーされる場合、変数はヒープにコピーされます。したがって、__block変数のアドレスは時間の経過とともに変化する可能性があります。

__block変数には、さらに2つの制限があります。可変長配列にすることはできません。また、C99可変長配列を含む構造体にすることもできません。

の代わりに、NSMutableArrayを使用してプレーンNSArrayを使用 してみてください

+ (id)arrayWithObject:(id)anObject

于 2012-04-09T15:44:11.607 に答える