AFNetworking2这段简单代码你看懂了吗?

2018-04-28  本文已影响63人  杭研融合通信iOS

AFNetworking作为开发者网络库的标配,发展了很多版本,我是从2.0开始使用,再到3.0的重大改版,虽然没有细致看过源码,但是多次调试,已经对源码比较熟悉。


来挑战~

也是真的是“只是在人群中偷偷看了你一眼,再也不能忘掉你容颜”,下面这段AFNetworking2时期(2015~2016年)的代码让我一直记忆犹新,大家来找茬,看看代码有没有问题 (重点标注的那段if else ):

- (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(), ^{
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
            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
}

希望大家先看下上面代码中if else逻辑,分析下有啥问题没?






初印象~

那时候真的是匆匆一瞥,闪念就是开源代码这位大神也会犯这么简单的错误? if和else中的 if (failure)这段逻辑明显是重复啊! 可以直接删掉一段,我们把它摘出来:

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;
              //  WTF!!! 下面这个if 不是上面if的重复吗 ???
                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 (failure)同样的逻辑,但是第二个 if (failure)前面有这样一句代码:

id responseObject = self.responseObject;

只是一个赋值,会对 if (failure)有什么影响吗?
但真的只是一个赋值吗?

我们习惯性思维通常是这样:取出self的属性responseObject的值,赋值给局部变量responseObject。通常情况这样理解没问题,但是这是建立在我们大多数情况不会重写属性的setter和getter方法! 如果这里重写了responseObject属性的setter和getter方法呢? 点击self.responseObject的 “jump to definition” 后我终于参透了:

- (id)responseObject 
{
    [self.lock lock];
    if (!_responseObject && [self isFinished] && !self.error) {
        NSError *error = nil;
        self.responseObject = [self.responseSerializer responseObjectForResponse:self.response data:self.responseData error:&error];
        if (error) {
            self.responseSerializationError = error;
        }
    }
    [self.lock unlock];

    return _responseObject;
}

可以看到在getter方法中,会对error再次赋予新的值,所以在 id responseObject = self.responseObject;后面的if中需要重新判断是否有error。


完结~

上一篇下一篇

猜你喜欢

热点阅读