0

我想知道这是否是让嵌套块在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 版本来访问数据。我所做的安全吗?

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 回答