Objective C 中的块编程的内存管理
我正在阅读以下有关调度队列中的完成块的 Apple 文档,但我无法理解其中的部分内容。该文档提到“为了防止队列过早释放,最初保留该队列并在分派完成块后释放它是至关重要的。”这与我的理解相矛盾,即块在其闭包中保留所有变量,这在块编程指南中提到。
我在这里缺少什么?该文档的片段粘贴如下:
完成块只是您在原始任务结束时分派到队列的另一段代码。调用代码通常在启动任务时提供完成块作为参数。任务代码所要做的就是在完成工作时将指定的块或函数提交到指定的队列。
清单 3-4 显示了使用块实现的平均函数。平均函数的最后两个参数允许调用者指定报告结果时要使用的队列和块。平均函数计算出其值后,会将结果传递到指定的块并将其分派到队列。为了防止队列过早释放,最初保留该队列并在分派完成块后释放它至关重要。 清单 3-4 在任务后执行完成回调
void average_async(int *data, size_t len, dispatch_queue_t queue, void (^block)(int))
{
// Retain the queue provided by the user to make
// sure it does not disappear before the completion
// block can be called.
dispatch_retain(queue);
// Do the work on the default concurrent queue and then
// call the user-provided block with the results.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
int avg = average(data, len);
dispatch_async(queue, ^{ block(avg);});
// Release the user-provided queue when done
dispatch_release(queue);
});
}
I was reading the following Apple documentation on completion block in dispatch queues, and I have trouble understanding part of it. The document mentions that "To prevent the queue from being released prematurely, it is critical to retain that queue initially and release it once the completion block has been dispatched." This contradicts my understanding that the block retains all the variables in its closure, which is mentioned in the Block Programming Guide.
What am I missing here? The snippet from the document is pasted below:
A completion block is just another piece of code that you dispatch to a queue at the end of your original task. The calling code typically provides the completion block as a parameter when it starts the task. All the task code has to do is submit the specified block or function to the specified queue when it finishes its work.
Listing 3-4 shows an averaging function implemented using blocks. The last two parameters to the averaging function allow the caller to specify a queue and block to use when reporting the results. After the averaging function computes its value, it passes the results to the specified block and dispatches it to the queue. To prevent the queue from being released prematurely, it is critical to retain that queue initially and release it once the completion block has been dispatched.
Listing 3-4 Executing a completion callback after a task
void average_async(int *data, size_t len, dispatch_queue_t queue, void (^block)(int))
{
// Retain the queue provided by the user to make
// sure it does not disappear before the completion
// block can be called.
dispatch_retain(queue);
// Do the work on the default concurrent queue and then
// call the user-provided block with the results.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
int avg = average(data, len);
dispatch_async(queue, ^{ block(avg);});
// Release the user-provided queue when done
dispatch_release(queue);
});
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这不是矛盾,而是误解。块保留它引用的所有objective-c 对象。其他对象类型使用自己的保留函数而不是标准函数。因此,运行时不可能知道如何保留块可能包含的每个变量。这就是为什么需要手动保留和释放队列的原因。
It is not a contradiction, but a misunderstanding. A block retains all objective-c objects that it references. Other object types use their own retain functions instead of a standard one. Therefore, it is impossible for the runtime to know how to retain every variable a block could contain. This is why the queue needs to be retained and released manually.