8

クラスに簡単なメソッドがあります。

- (void)getFormWithBlock:(DataCenterResultBlock)block {
    [SomeClass doSomeLongOperationWithParam:someParam 
                                  completionBlock:^(NSData *data, NSURLResponse *response) {
                                      //Success
                                      block(aVar, YES);
                                  } errorBlock:^(NSError *error) {
                                      //Failed
                                      block(nil, NO);
                                  }];
}

ブロックがスタックに割り当てられ、呼び出しツリーが巻き戻されると消えてしまうため、非同期で何かを実行している場合は、ブロックをヒープにコピーする必要があることを読みました。

しかし、ここでは、ヒープにコピーしていませんが、それでもクラッシュは発生しません。なんで?ありがとう

4

2 に答える 2

11

ブロック変数は、ARCコンパイラによって自動的にヒープにコピーされます

7.5。ブロック

..。

保持可能なオブジェクト所有者タイプの__block変数は、スタックコピーから移動した結果でヒープコピーを初期化することにより、スタックから移動されます。

編集私は質問を誤解したと思います:あなたはブロック変数ではなく、ブロックオブジェクト自体について尋ねました。この場合の答えは少し異なりますが、要約すると同じです。ARCは自動的に正しいことを行います。

ARCは、現在のスコープが戻った後にブロックリテラルを使用する場合は、ブロックリテラルをコピーする必要があることを認識しています。非ARCコードは、返されたブロックを明示的にコピーして自動解放する必要があります。

return [[^{
    DoSomethingMagical();
} copy] autorelease];

ARCの場合、これは単純に次のようになります。

return ^{ DoSomethingMagical(); };

ここから)

于 2012-07-11T14:00:44.733 に答える
1

[SomeClass doSomeLongOperationWithParam:completionBlock:errorBlock:]完了ブロックとエラーブロックをコピーする必要があります。

そのメソッドの実装を見ると、おそらく正しいことをして、渡したブロックをコピーしています。ARCまたはARCなしの場合、そのメソッドはそれらのブロックをコピーする必要があります。

于 2012-08-21T20:41:48.483 に答える