记录dispatch_group_enter()和dispatch_group_leave()的使用

        今天在读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():

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.

dispatch_group_leave():
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.
        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()来实现:

dispatch_group_enter(group); 
        [self performBlock:^(){ 
            block(); 
            dispatch_group_leave(group); 
}]; 
         异步任务回调后才算这个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

你可能感兴趣的:(ios点滴)