我想知道这是否是使嵌套块在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版本来访问数据。我在做什么安全?
答案 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];