Objective C ASIHTTPRequest在完整块中嵌套GCD块

时间:2012-09-19 20:12:53

标签: objective-c automatic-ref-counting asihttprequest objective-c-blocks grand-central-dispatch

我想知道这是否是使嵌套块在Objective C中处理同一变量的正确方法,而不会导致任何内存问题或与ARC崩溃。它以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版本来访问数据。我在做什么安全?

2 个答案:

答案 0 :(得分: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。虽然我最初注意到请求和自我都保留在原帖中,但我认为适当的措施是在必要时采取。这对我来说不是一个错误的决定。

因此,有几种方法可以打破此请求的保留周期,但使用弱引用可能是最安全和最佳选择。

请参阅上述代码中标有// EDIT的行。

答案 1 :(得分: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];