0
- (void)netServiceDidResolveAddress:(NSNetService *)サービス{
    dispatch_async(self.downloadQueue, ^{
        NSData *data = [self downloadFromRemoteService:service];

        dispatch_async(self.storeQueue, ^{
            int img = [self.imageStore addImage:data];

            dispatch_saync(self.renderQueue, ^{
                [self renderThumbnail:img];

                dispatch_async(dispatch_get_main_queue(), ^{
                    [[自分のサムネイルViewForId:img] setNeedsDisplay:YES];
                });
            });
        });
    });
}

これは Apple WWDC2012 のコードです 《Asynchronous Design Patterns with Blocks, GCD, and》, ブロック内の強参照としての 'self', このコードは大丈夫ですか? または、この状況でリークを回避する方法は?</p>

4

3 に答える 3

0

このコードにはself保持self.downloadQueue(および他のキュー) としての保持サイクルがあり、ここにあるブロックを含め、それにディスパッチされたすべてのブロックを保持しselfます。 )。

ただし、ブロックがキューで実行されると、キューは (うまくいけば) ブロックを解放し、サイクルを中断するため、一時的な保持サイクルです。

于 2013-09-02T23:12:03.800 に答える
0

ブロック内で言及されたオブジェクトは自動的に保持されます。ブロックの割り当てが解除されたときに解放されました。したがって、このコードは問題ありません。あなたの self-object が self を内部に持つブロックの所有権を取得すると、問題が発生します。したがって、ブロックが不要になったらブロックを解放するだけです。

于 2013-09-02T13:56:05.307 に答える
0

いいえ、self漏れません。selfただし、最後のブロックが実行されるまで保持されます。最後のブロックが終了すると、ブロックの割り当てが解除され、次に が解放されますself。その時点で、 IFF のみに他に強い参照がなくself、割り当てが解除されます。

編集:

私はこれについて言及せずにはいられませんでした(サンプルはApple自身からのものなので、塩の場合は穀物と一緒に取ってください;))

したがって、一番上にメソッドがありdownloadFromRemoteServiceます。これがネットワーク リクエストであることは明らかです。ネットワーク要求は本質的に_非同期_です。

非同期操作の属性の 1 つは、この操作を真の方法で「同期」することができなくなることです。一度非同期 - 常に非同期。

コード サンプルから明らかなことは、ネットワーク リクエストが奇妙にも十分に同期的であることです。

非同期タスクを同期ラッパーにラップするとどうなりますか? まあ、少なくとも「準最適」です。呼び出し元のスレッドは、結果が利用可能になるまですぐにブロックされ、結果を返すだけです。これはかなりの量のリソースを浪費します (スレッドは限られているため、作成にコストがかかり、かなりの量の RAM が必要です)。

というわけで、このコードには「コード臭」があります。それは「悪いプログラミング手法」です。これを改善する必要があります。;)

于 2013-09-03T17:14:35.133 に答える