0

ARC とブロックに問題がありましたが、問題は解決しました。残念ながら、私は正確に何が起こっているのかわかりません。私の状況についてもっと知りたいと思っています.

もともと、これを行うコードがありました

for(__block id<Foo> object in objects) {
    foo download:someParm
         success:^{
            object.state = StateNewState; 
         }
    ];
}

これにより、保持の不均衡が発生しました。オブジェクトがアクセスされ、すでに割り当てが解除されていると言われると、クラッシュが発生します。「copy」属性を実装して使用するクラスを作成し、ダウンロード関数の success パラメータに渡されたブロックを保存する successBlock プロパティを作成しました。このコードを次のように置き換えました

for(id<Foo> object in objects) {
    foo download:someParm
         success:^(id<Foo> successObject){
            successObject.state = StateNewState; 
         }
    ];
}

オブジェクトの割り当て解除エラーはなくなりましたが、リークしていないかどうかを確認するためにインストゥルメントをまだ実行していません。__block を使用するとオブジェクトが何度も解放されてしまい、その理由がわかりません。この問題の原因については調査を続けますが、残りの皆さんが考えるには興味深い問題だと思いました。

objects 配列は、この記事の前半で書き留めたコードの次の行で作成された、自動解放された配列であったことに注意してください。それは問題ではないと思いますが、私はそこを通り抜けると思いました。この記事に掲載したコードは正確なコードではありません。これは仕事で使用していて、そこには毛羽立ちがたくさんあるからです。しかし、for ループで作成される他のオブジェクトはありません。

アプリがクラッシュすると、ダウンロードが実行され、後でコールバックが実行されます。ちなみに、私は ASIHttp を使用しています。もう一度ダウンロードしようとすると、オブジェクトの割り当てが解除され、デリゲートが無効になっているため、実行され、コールバックが呼び出されません。この後、オブジェクトへのポインターを含む辞書によってオブジェクトにアクセスすると、クラッシュします。

4

2 に答える 2

4

ブロックプログラミングトピックは言う:

ブロック内でインスタンス変数を使用すると、オブジェクト自体が保持されます。特定のオブジェクト変数に対してこの動作をオーバーライドする場合は、__blockストレージタイプ修飾子を使用してマークを付けることができます。

ARCを使用している場合、ブロックがコピーされて後で解放されるときに、オブジェクト変数が自動的に保持および解放されます。

したがって、を使用しない場合は__block、変数が保持されていることがわかると思います。たとえば、これは私にとってはうまくいくようです:

NSMutableArray *array = [[NSMutableArray alloc] init];

// add two custom objects to that array

[array addObject:[[MyObject alloc] initWithText:@"One" number:1]];
[array addObject:[[MyObject alloc] initWithText:@"Two" number:2]];
[array addObject:[[MyObject alloc] initWithText:@"Three" number:3]];

// now replace the text field in each of the three objects with the word "Done"

for (MyObject *object in array)
{
    [self blockTestInvocation:^{
        NSLog(@"%s %@", __FUNCTION__, [NSDate date]);

        object.text = @"Done";
    }];
}

渡されたブロックを同期的に呼び出した場合、の有無は__block重要な影響を与えないことがわかりましたblockTestInvocationが、ブロックを非同期で呼び出すように設定した場合(配列とオブジェクトが解放された後)、オブジェクトが保持されている__blockことを確認し、それによって恐ろしい「割り当て解除されたインスタンスに送信されたメッセージ」を防止しました(リークもありませんでした)。ただし、を使用する__blockと、オブジェクトは保持されないため、コードブロックがオブジェクトを参照しようとするまでにオブジェクトの割り当てが解除される可能性があります。

于 2012-05-30T02:43:56.900 に答える