0

これが、メモリの問題やARCでのクラッシュを引き起こすことなく、ObjectiveCの同じ変数でネストされたブロックを機能させる正しい方法であるかどうか疑問に思いました。これは、ASIHttpRequestの完全なブロックで始まります。

MyObject *object = [dataSet objectAtIndex:i];

ASIHTTPRequest *request = [[ASIHTTPRequest alloc]initWithURL:@"FOO"];

__block MyObject *mutableObject = object;

[request setCompleteBlock:^{

      mutableObject.data = request.responseData;

      __block MyObject *gcdMutableObject = mutableObject;

      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{

              [gcdMutableObject doLongComputation];

              dispatch_async(dispatch_get_main_queue(),^{

                     [self updateGUIWithObject:gcdMutableObject];
              }); 

      });

[request startAsynchronous];

私の主な関心事は、ディスパッチキューをネストし、前のキューの__blockバージョンを使用してデータにアクセスすることです。私がしていることは安全ですか?

4

2 に答える 2

2
// Under ARC the blocks will automatically retain <object>
MyObject *object = [dataSet objectAtIndex:i];
ASIHTTPRequest *request = [[ASIHTTPRequest alloc]initWithURL:@"FOO"];
__weak ASIHTTPRequest *weakRequest = request;                        // EDIT
[request setCompleteBlock:^{
    // <object> is retained by the block.
    // Changing a property of <object> but not <object> itself.
    ASIHTTPRequest *request = weakRequest;                           // EDIT
    if (!request) return;                                            // EDIT
    object.data = request.responseData;    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
        // <object> retained by this block too...
        [object doLongComputation];
        dispatch_async(dispatch_get_main_queue(),^{
            // <object> retained by this block too
            // Note, <self> is also retained...
            // Use the same "weak" trick if you don't want this      // EDIT
            [self updateGUIWithObject:object];
        });
    });
}];
[request startAsynchronous];

編集

endyは有効なポイントをもたらします (ただし、使用__usnafe_unretainedは一般的に避けるべきです。元の投稿では request と self の両方が保持されていることに最初に注意しましたが、必要に応じて適切な措置が講じられると想定していました。それは私の側の間違った決定ではありませんでした。 .

したがって、このリクエストの保持サイクルを中断する方法はいくつかありますが、ここでは弱参照を使用するのがおそらく最も安全で最良の選択です。

// EDIT上記のコードで でマークされた行を参照してください。

于 2012-09-19T22:47:31.423 に答える
0

同じオブジェクトへのすべてのポインターで少し迷子になりましたが、これがあなたが探しているものだと思います。

__block MyObject *object = [dataSet objectAtIndex:i];

__unsafe_unretained ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"FOO"]];


[request setCompleteBlock:^{

      object.data = request.responseData;


      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{

              [object doLongComputation];

              dispatch_async(dispatch_get_main_queue(),^{

                     [self updateGUIWithObject:object];
              }); 

      });
}];
[request startAsynchronous];
于 2012-09-19T21:36:02.780 に答える