今天在读AFNetworking源码的时候看到很多GCD的使用,查阅相关资料了解了一些常用方法后记录了下来,加强记忆,便于以后查阅。
源码片段如下:
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
// completionBlock is manually nilled out in AFURLConnectionOperation to break the retain cycle.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
#pragma clang diagnostic ignored "-Wgnu"
self.completionBlock = ^{
if (self.completionGroup) {
dispatch_group_enter(self.completionGroup);
}
dispatch_async(http_request_operation_processing_queue(), ^{
if (self.error) {
if (failure) {
dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(self, self.error);
});
}
} else {
id responseObject = self.responseObject;
if (self.error) {
if (failure) {
dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(self, self.error);
});
}
} else {
if (success) {
dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{
success(self, responseObject);
});
}
}
}
if (self.completionGroup) {
dispatch_group_leave(self.completionGroup);
}
});
};
#pragma clang diagnostic pop
}
初次阅读这段代码的时候,对dispatch_group_enter()和dispatch_group_leave()的用法不是很了解,苹果官方的文档说明如下:
dispatch_group_enter():
<span style="font-family:Courier New;font-size:10px;">Calling this function increments the current count of outstanding tasks in the group. Using this function (with dispatch_group_leave) allows your application to properly manage the task reference count if it explicitly adds and removes tasks from the group by a means other than using the dispatch_group_async function. A call to this function must be balanced with a call to dispatch_group_leave. You can use this function to associate a block with more than one group at the same time.</span>
dispatch_group_leave():
<span style="font-family:Courier New;">Calling this function decrements the current count of outstanding tasks in the group. Using this function (with dispatch_group_enter) allows your application to properly manage the task reference count if it explicitly adds and removes tasks from the group by a means other than using the dispatch_group_async function.A call to this function must balance a call to dispatch_group_enter. It is invalid to call it more times than dispatch_group_enter, which would result in a negative count.</span>
dispatch_group_enter()显式的指明一个任务执行块进入了这个组,dispatch_group_leave()显式表明执行块执行完毕,移除出组。对于同步任务,这两个方法结合起来的效果等同于dispatch_group_async();而当执行的任务为异步的时候,用dispatch_group_async()就会出现问题,如:
dispatch_group_async(group, queue, ^{
[self performBlock:^(){
block();
}];
});
上述代码中,block()就无法得到执行。这个时候,需要结合dispatch_group_enter()和dispatch_group_leave()来实现:
<span style="font-size:10px;">dispatch_group_enter(group);
[self performBlock:^(){
block();
dispatch_group_leave(group);
}]; </span>
异步任务回调后才算这个group任务完成。
另外,上述代码中出现了如下片段:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-retain-cycles"
#pragma clang diagnostic ignored "-Wgnu"
...
...
#pragma clang diagnostic pop
其作用是忽略中间代码的循环引用的警告以及一些特定的编译警告,具体内容可查阅
http://clang.llvm.org/docs/UsersManual.html#diagnostics_pragmas