美文网首页
AFNetworking2这段简单代码你看懂了吗?

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

作者: 杭研融合通信iOS | 来源:发表于2018-04-28 22:57 被阅读63次

    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。


    完结~

    相关文章

      网友评论

          本文标题:AFNetworking2这段简单代码你看懂了吗?

          本文链接:https://www.haomeiwen.com/subject/gwbnlftx.html