AFNetworking3.0升级记录1

前言

公司最近刚刚赶完一个版本需求,准备对AFNetworking进行升级。其实年前就做过这方面研究,当时是因为有传言2017年后苹果要求升级https而老的网络底层不支持,必须升级。后来因为新需求比较赶,又在网上找到可靠消息说网上都是谣传并没有强制升级于是就搁置了下来。

简介

AFNetworking是对IOS本身网络请求的封装,有两种方式NSURLConnection和NSURLSession。

因为AFNetworking1.0就是构建于NSURLConnection之上的,等到AFNetworking2.0才NSURLSession的方式,之后的AFNEtworking3.0更去掉了NSURLConnection的方式。关于原因可以点击这里

所以这一次我的主要任务就是从之前的NSURLConnection(AFHTTPRequestOperationManager)升级到NSURLSession(AFHTTPSessionManager)。

当前网络层

刚开始我得先把当前的网络层理一下,看下哪些地方用到网络请求。最后发现也复杂,一共两种不一样的地方:
1.最主要的一个就是对一般网络POST请求的封装。
2.上传一些诸如图片、音频等文件的PUT请求。

看上去挺简单的,但因为代码经过多代人之手,难免有些冗余代码质量也不是特别高,就像上传附件的封装就有两份在程序中都有用到,为了尽量不产生新问题我也就对它们都做修改。

下面是之前的实现方式的主要流程,一些代码上的坑我就不放出来了。

1.首先是一般网络POST请求的封装。

(1)首先是单例的实现基础设置:

+ (instancetype) sharedClient{
    
    static NetworkManager *_sharedClient = nil;
    static dispatch_once_t _onceTocken;
    dispatch_once(&_onceTocken, ^{
        
        if (appDelegate.apiBaseUrlStr) {
            _sharedClient = [[NetworkManager alloc] initWithBaseURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@",appDelegate.apiBaseUrlStr]]];
        } else {
            _sharedClient = [[NetworkManager alloc] initWithBaseURL:[NSURL URLWithString:@"(null)"]];
        }
        _sharedClient.llOperationQueue = [[NSOperationQueue alloc] init];
        //最大并发数
        _sharedClient.llOperationQueue.maxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount;
        [_sharedClient.requestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [_sharedClient.requestSerializer setValue:ApiVersion forHTTPHeaderField:@"User-Agent"];
        [_sharedClient.requestSerializer setTimeoutInterval:30];
        _sharedClient.bstart = NO;
        _sharedClient.apiCount = 0;
    });
    
    return _sharedClient;
}

(2)POST请求对外接口:

- (NSURLSessionDataTask *)POST:(NSString *)URLString
                parameters:(id)parameters
                  progress:(void (^)(NSProgress * _Nonnull))uploadProgress
                success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nonnull))success
                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
    if (![CommonClass checkNetworkRechable]) {
        failure(nil,[NSError errorWithDomain:@"www.mHealth.com" code:-1009 userInfo:nil]);
        return nil;
    }
    if((!appDelegate.apiBaseUrlStr || appDelegate.apiBaseUrlStr.length < 1) && !_bstart)
    {
#ifdef DEBUG_MODE
        NSLog(@"No baseurl, need network access");
#endif
        
        [self.llOperationQueue setSuspended:true];
        LandbalancerSessionOperation *llsessionOperation = [[LandbalancerSessionOperation alloc] initWithURLString:URLString parameters:parameters success:success failure:failure];
        [self.llOperationQueue addOperation:llsessionOperation];
        
        _bstart = true;
        [self requestApi];
        
        return nil;
    }
    else
    {
        return [super POST:URLString parameters:parameters progress:uploadProgress success:success failure:failure];
    }
}

这边有个判断,如果没有baseurl,则要把当次请求先挂起,先去请求version接口,完成后再开始当次请求。

2.附件上传

我们这边上传附件的流程是这样的,先进行POST请求将我们拼接好的文件名和文件大小给云端,云端这时候会返回我们需要上传到的url,我们再通过这个url进行PUT上传。
(1)POST请求将文件名和长度给云端:

#pragma mark - NSOperation
-(void)main
{
    [self.lock lock];
    if(!self.file.rawData)
    {
        return;
    }
    NSUInteger size = self.file.rawData.length;
    if (size <= 0)
    {
        //        [self removeOperationFromDB];
        return;
    }
    if(!self.file.key || self.file.key.length < 1)
    {
        return;
    }
    
    NSMutableDictionary *parameterMDic = [[NSMutableDictionary alloc] init];
    [parameterMDic setObject:[NSNumber numberWithInteger:size] forKey:@"size"];
    [parameterMDic setObject:self.file.key forKey:@"filename"];
    [parameterMDic setObject:[appDelegate.userDefaults objectForKey:AccessToken] forKey:AccessToken];
    [[NetworkManager sharedClient] POST:API_ATTACHMENT parameters:parameterMDic success:^
     (AFHTTPRequestOperation *__unused task, id JSON){
         
#ifdef DEBUG_MODE
#endif
         [self completionBlock:API_ATTACHMENT withData:JSON withUserInfo:nil];
         
     }failure:^
     (AFHTTPRequestOperation *__unused task, NSError *error){
         
#ifdef DEBUG_MODE
#endif
         
         [self failedBlock:API_ATTACHMENT withError:error withUserInfo:nil];
     }];
    [self.lock unlock];
}

(2)这里把云端返回数据统一判断,未完成就进行PUT请求上传文件,直到完成:

-(void)dealAttachmentResponse:(NSDictionary *)responseDic
{
    [self.lock lock];
    NSString *finishStr = [responseDic objectForKey:@"finished"];
    if ([CommonClass bNull:(NSNull *)finishStr] && finishStr)
    {
        _finishStr = finishStr;
    }
    else
    {
        _finishStr = nil;
    }
    NSNumber *lenNum = [responseDic objectForKey:@"len"];
    NSString *methodStr = [responseDic objectForKey:@"method"];
    if ([CommonClass bNull:(NSNull *)methodStr] && methodStr)
    {
        _methodStr = methodStr;
    }
    else
    {
        _methodStr = nil;
    }
    NSNumber *offNum = [responseDic objectForKey:@"off"];
    NSString *urlStr = [responseDic objectForKey:@"url"];
    if ([CommonClass bNull:(NSNull *)urlStr] && urlStr)
    {
        _urlStr = urlStr;
    }
    else
    {
        _urlStr = nil;
    }
    //    _urlStr = [_urlStr stringByReplacingOccurrencesOfString:@"db.mcloudlife.com" withString:@"115.236.76.184"];
    
    if ([_finishStr isEqualToString:@"Y"] || [lenNum integerValue] <= 0)
    {
        //上传完成
//        NSString *imgName = [urlStr lastPathComponent];
//        self.uploadOneFileSucceeded(imgName, self.fileIndex, self.file.key);
        self.uploadOneFileSucceeded(_urlStr, self.fileIndex, self.file.key);
        return;
    }
    
    NSRange range = NSMakeRange([offNum integerValue], [lenNum integerValue]);
    NSData * data = [self getUploadImgData:self.file.rawData withRange:range];
    NSInputStream *inputStream = [[NSInputStream alloc] initWithData:data];
    [self httpRequestThroughPut:inputStream];
    
    [self.lock unlock];
}

- (NSData *)getUploadImgData:(NSData *)imgData withRange:(NSRange)range
{
    NSUInteger length =  [imgData length];
    if (length < (range.location + range.length)) {
        return nil;
    }
    NSData *subData = [imgData subdataWithRange:range];
    return subData;
}

(3)PUT请求上传数据,失败重试,成功则再以上面的方法判断是否完成。

#pragma mark - NetWork_Upload
-(void)httpRequestThroughPut:(NSInputStream *)inputStream
{
    if (inputStream && _urlStr)
    {
        AFHTTPRequestOperationManager *requestOperationManager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:nil];
        //设置httpHeader
        [requestOperationManager.requestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        [requestOperationManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [requestOperationManager.requestSerializer setValue:[NSString stringWithFormat:@"mCloud %@",[appDelegate.userDefaults objectForKey:AccessToken]] forHTTPHeaderField:@"Authorization"];
        [requestOperationManager.requestSerializer setValue:@"db.mcloudlife.com" forHTTPHeaderField:@"Host"];
        //设置超时时间
        [requestOperationManager.requestSerializer setTimeoutInterval:-1];
        
        //put请求
        AFHTTPRequestOperation *requestOperation = [requestOperationManager PUT:_urlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
            if (![NetworkErrorDeal getErrorMsgWithResponseData:responseObject])
            {
                if(![responseObject isKindOfClass:[NSDictionary class]])
                {
                    return;
                }
                [self dealResponse:responseObject];
            }
            else
            {
                //尝试重新请求
                if(_retryCount <= 0)
                {
                    return ;
                }
                _retryCount--;
                dispatch_queue_t  queue= dispatch_queue_create("dealFileAttachmentResponse", NULL);
                dispatch_async(queue, ^{
                    [self httpRequestThroughPut:inputStream];
                });
            }
            
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            
            if(_retryCount <= 0)
            {
                return ;
            }
            _retryCount--;
            dispatch_queue_t  queue= dispatch_queue_create("dealImageAttachmentResponse", NULL);
            dispatch_async(queue, ^{
                [self httpRequestThroughPut:inputStream];
            });
        }];
        
        __block AFHTTPRequestOperation *progressOperation = requestOperation;
        
        [requestOperation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
            
//        }]
        
//        [requestOperation setUploadProgressBlock:^(NSUInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) {
            
            double percent = totalBytesWritten * 1.0 / self.file.fileSize;
            
            if (self.uploadOneFileProgress) {
                self.uploadOneFileProgress(progressOperation, self.fileIndex, percent);
            }
        }];
        
        //设置httpbodystream
        [requestOperation setInputStream:inputStream];
    }
}

好了,这些就是之前的网络层,等我给测试进行整体测试如果没问题的话,我会在下一篇记录主要的修改。
另外大家如果有关于升级AFNetworking3.0的问题的话可以留下评论,指教不敢当,互相讨论吧:)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容

  • iOS开发系列--网络开发 概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博、微信等,这些应用本身可...
    lichengjin阅读 3,658评论 2 7
  • 目录 网络基本概念 TCP/IP协议簇基本概念 HTTP 网络开发技术解决方案 数据解析 网络优化 1. 网络基本...
    Ryan___阅读 1,357评论 1 0
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,094评论 4 62
  • 在苹果彻底弃用NSURLConnection之后自己总结的一个网上的内容,加上自己写的小Demo,很多都是借鉴网络...
    付寒宇阅读 4,278评论 2 13
  • 北京西山,上班路上随拍,那天天空格外美丽。 晚霞,小区随拍,生活并不缺少美。 朝霞,娘家随拍,冬季也格外动人。 披...
    黄泗娘家花满溪阅读 243评论 4 5