0

以下に貼り付けたコードで、'showResultToUser' への呼び出しが実行されたときにオブジェクトがまだ存在していること、および既に解放されたオブジェクトへの呼び出しを取得しないことを確認するにはどうすればよいですか?

__block MyClass pSelf = self;

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^
{
    [pSelf doSomeBackgroundWork];
    dispatch_async(dispatch_get_main_queue(), ^
    {
        [pSelf showResultToUser];
    });
});
4

4 に答える 4

0

この質問は、__block の割り当て動作と、pSelf 変数自体が安定したストレージにあるかどうかによって混乱していると思います (つまり、スタック フレーム内で宣言されている場合でも、__block によってヒープに割り当てられます)。さらに重要なのは、ARC がない場合 (使用していないと言う)、ブロックを dispatch_async() に渡す前にそのようなオブジェクトを明示的に保持し、ブロック内から解放することです。dispatch_async のマニュアル ページを参照し、例として async_read() 関数が作成されている「COMPLETION CALLBACKS」というラベルの付いたセクションを探します。宛先キューがどのように保持されてから解放されるかを確認してください。同じパターンに従うことで、トラブルを回避できます。

ブロック内の ObjC インスタンス変数オブジェクトは、「無料で」保持動作を自動的に取得することに注意してください (http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html)。コードをより明確にするため(私見)、保持/解放動作を明示的にしても害はありません。

于 2012-09-11T00:18:26.897 に答える
0

Apple 開発者の Web サイトから:

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

これは、リリースされないことを意味します。


それ以外に、ハンドルが有効な変数を参照しているかどうかを確認する方法はありません。それ解放された場合、別の有効な (ただし異なる) 変数によって再利用される可能性があるためです。

于 2012-09-10T05:00:10.717 に答える
0

__block修飾された変数を削除することで、オブジェクトの割り当てが解除されるのを防ぐことができます。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^
{
    [self doSomeBackgroundWork];
    dispatch_async(dispatch_get_main_queue(), ^
    {
        [self showResultToUser];
    });
});

参照されたオブジェクトの有効期間を不必要に延長する可能性がありますが、他に何も保持されていない場合、内部ブロックの実行の最後に割り当てが解除されます。

于 2012-09-12T05:05:39.593 に答える