NSURLSession和AFNetWorking的使用解读

本文对比分析了iOS平台上的NSURLSession和AFNetworking两个网络请求框架。NSURLSession作为苹果官方提供的API,功能强大且灵活;而AFNetworking则在此基础上进一步封装,提供了更便捷的请求和响应处理方式。文中还详细介绍了如何使用这两个框架进行网络请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一,概述

做过Android开发的人员都知道,Google不但有系统自带的URLConnection和HttpClient来处理网络请求,而且还有好多开源的框架,比如Volley,OK3,Xutils等。

IOS作为另一个具有庞大开发者队伍的平台当然也不干落后,除了先后更新自己系统自带的网络框架NSURLConnection到NSURLSession,还有好多三方的,其中用户最多还在更新的就是AFNetworking了。

源码:https://github.com/XinRan5312/QXIOSHttp  欢迎Fork,这个小Demo封装了NSURLSession和AFNetWorking两个网络框架的使用

二,NSURLSession

       NSURLSession是核心的管理类,通过NSURL,NSURLRequest(NSMutableURLRequest),还有一个最重要的网络处理策略配置类NSURLSessionConfiguration,包括配置缓存策略,Header和Cookie等,其中有三个类方法获得默认的NSURLSessionConfiguration。

       当这一切都准备好以后NSURLSessionTask就该出场了,从名字大家就可以明白,他就是封装任务的,包括三个子类,NSURLSessionDataTask,NSURLSessionDownLoadTask,NSURLSessionUploadTask,从名字大家都是知道他们是干嘛的了,不过这只是封装任务,并没有开始执行任务,如果需要执行任务,需要[task resum],也可取消,停止任务,看如下实例代码:

@interfaceQXHTTPMenager()

@property(nonatomic,nullable)NSMutableDictionary<NSString*,NSURLSessionTask*> *taskDic;

@end

@implementation QXHTTPMenager


+(instancetype)ShareQXHTTPMenager{


    staticQXHTTPMenager *sharedManager = nil;

    staticdispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        sharedManager = [[selfalloc] init];

    });

    return sharedManager;


}

-(instancetype)init{

    if([superinit]){

        self.requestsDictionary=[[NSMutableDictionaryalloc]init];

        self.baseUrl=@"http://www.baidu.com/";

        returnself;

    

    }else{

    

        returnnil;

    }

}

-(void)startRequest:(QXBaseRequest *)request{

    if(request){

        request.requestStatus=QXHTTPRequestStatusStart;

        NSURL *url=[selfcreateNSURL:request];

        if(url){

         

            if(request.httpMethod){

                

                QXHTTPMethod method=request.httpMethod;

                NSMutableURLRequest *req=[NSMutableURLRequestrequestWithURL:url];

               

                switch (method) {

                    caseQXHTTPMethodGet:

                       req.HTTPMethod=@"GET";

                        break;

                    caseQXHTTPMethodPost:

                        req.HTTPMethod=@"POST";

                        break;

                    caseQXHTTPMethodPut:

                         req.HTTPMethod=@"PUT";

                        break;

                    caseQXHTTPMethodPatch:

                         req.HTTPMethod=@"PATCH";

                        break;

                    caseQXHTTPMethodOptions:

                         req.HTTPMethod=@"OPTIONS";

                        break;

                    caseQXHTTPMethodDelete:

                         req.HTTPMethod=@"DELETE";

                        break;

                    caseQXHTTPMethodConnect:

                         req.HTTPMethod=@"CONNECT";

                        break;

                    caseQXHTTPMethodTrace:

                         req.HTTPMethod=@"TRACE";

                        

                        break;

                    default:

                         req.HTTPMethod=@"GET";

                        break;

                }

                NSURLSession *session=[selfcreateNSURLSession:request];

                NSURLSessionTask *task=[selfcreateURLSessionTask:session request:request nsRequest:req];

                if(request.requestTag){

                    [task setTaskDescription:request.requestPath];

                    [_taskDicsetObject:task forKey:request.requestTag];

                    

                    [self.requestsDictionarysetObject:request forKey:request.requestTag];

                    

                }

                [task resume];

                request.requestStatus=QXHTTPRequestStatusDoing;

                

            }

            

        }


    

    }


}



-(NSURLSessionTask*)createURLSessionTask:(NSURLSession*) session request:(QXBaseRequest*)request nsRequest:(NSMutableURLRequest*) nsRequest{

    NSURLSessionTask * task=nil;

    QXHTTPReqeustType requestType=request.requestType;

    if(requestType==QXHTTPReqeustTypeData){

        task=[session dataTaskWithRequest:nsRequestcompletionHandler:^(NSData* data,NSURLResponse* response,NSError* error){

            [selfhandleResponse:response data:dataerror:error request:request];

        }];

    }elseif(requestType==QXHTTPReqeustTypeUpLoadFiles){

    

        task=[session uploadTaskWithRequest:nsRequestfromFile:[selfcreateNSURL:request] completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {

            [selfhandleResponse:response data:dataerror:error request:request];

        }];

    }elseif(requestType==QXHTTPReqeustTypeDownLoadFiles){

        task=[session dataTaskWithRequest:nsRequestcompletionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {

             [selfhandleResponse:response data:dataerror:error request:request];

        }];

    

    }


    return task;

}

-(void)handleResponse:(NSURLResponse*)response data:(NSData*)data error:(NSError*)error request:(QXBaseRequest*) request{


    

    if(request.callback){

        

        QXHTTPResponse *httpResponse=[[QXHTTPResponsealloc]init];

        

        httpResponse.data=data;

        httpResponse.response=response;

        httpResponse.request=request;

        httpResponse.error=error;

        

        /**

         NSJSONReadingOptions:

             NSJSONReadingMutableContainers:返回可变容器,NSMutableDictionaryNSMutableArray

         

             NSJSONReadingMutableLeaves:返回的JSON对象中字符串的值为NSMutableString,目前在iOS 7上测试不好用,应该是个bug,参见:

              http://stackoverflow.com/questions/19345864/nsjsonreadingmutableleaves-option-is-not-working

         

              NSJSONReadingAllowFragments:允许JSON字符串最外层既不是NSArray也不是NSDictionary,但必须是有效的JSON Fragment。例如使用这个选项可以解析 @“123” 这样的字符串。

              如果是0就是返回不了变的NSDictionary或者NSArray

         注:其实我们用NSJSONSerialization也可以解析网络请求出来的的结果,只是它只是半自动

         */

        NSDictionary *jsonObject=[NSJSONSerializationJSONObjectWithData:data options:NSJSONReadingMutableLeaveserror:nil];

        [QXYYModeljson2Model:jsonObject model:request.responseReultObj];

        

        request.callback(httpResponse);

//        [NSJSONSerialization JSONObjectWithStream:<#(nonnull NSInputStream *)#> options:<#(NSJSONReadingOptions)#> error:<#(NSError * _Nullable __autoreleasing * _Nullable)#>];

        

        if(error){

         request.requestStatus=QXHTTPRequestStatusError;

        }else{

         request.requestStatus=QXHTTPRequestStatusFinished;

            [_requestsDictionaryremoveObjectForKey:request.requestTag];

            [_taskDicremoveObjectForKey:request.requestTag];

        }

       

       

    }

}


-(NSURLSession*)createNSURLSession:(QXBaseRequest*)request{

    NSURLSession *session=nil;

    switch (request.configType) {

        caseQXHTTPConfigurationTypeDefault:

               session=[NSURLSessionsessionWithConfiguration:request.configution.getDefaultConfigution];

            break;

        caseQXHTTPConfigurationTypeCustom:

               session=[NSURLSessionsessionWithConfiguration:request.configution.customConfigution];

            break;

        caseQXHTTPConfigurationTypeOther:

            session=[NSURLSessionsessionWithConfiguration:request.configution.customConfigution];

            break;

        default:

            session=[NSURLSessionsessionWithConfiguration:request.configution.customConfigution];

            break;

    }


    return session;


}

-(NSURL*)createNSURL:(QXBaseRequest*) request{

    NSURL *nsUrl=nil;

    if(request==nil)return nil;

    if(request.requestPath){

        NSString *url=[self.baseUrlstringByAppendingPathComponent:request.requestPath];

        if(request.paramsDictionary){

            [url stringByAppendingPathComponent:@"?"];

            for (NSString* keyin [request.paramsDictionaryallKeys]) {

                [url stringByAppendingString:[NSStringstringWithFormat:@"%@=%@&",key,[request.paramsDictionaryvalueForKey:key]]];

            }

            NSInteger len=[urllength];

            NSRange rang=NSMakeRange(0, len-1);

            url=[url substringWithRange:rang];

        }

        nsUrl=[NSURLURLWithString:url];

        

    }else{

        nsUrl=[NSURLURLWithString:self.baseUrl];

    }

    return nsUrl;

}

-(void)stopRequestByTag:(NSString *)tag{

    QXBaseRequest *request=[self.requestsDictionaryvalueForKey:tag];

    if(request){

        NSURLSessionTask *task=[_taskDicvalueForKey:tag];

        if(task&&[request.requestPathisEqualToString:[task taskDescription]]){

              if(request.requestStatus==QXHTTPRequestStatusStart||request.requestStatus==QXHTTPRequestStatusDoing){

            [task suspend];

            request.requestStatus=QXHTTPRequestStatusStop;

            if(request.stopBlock){

                request.stopBlock(YES);

            }

        

              }

        }

        

    }


}

-(void)stopAllRequests{

    for(NSString* tagin [self.requestsDictionaryallKeys]){

        [selfstopRequestByTag:tag];

    }

}


-(void)cancelRequestByTag:(NSString *)tag{

    QXBaseRequest *request=[self.requestsDictionaryvalueForKey:tag];

    if(request){

        NSURLSessionTask *task=[_taskDicvalueForKey:tag];

        if(task&&[request.requestPathisEqualToString:[task taskDescription]]){

            if(request.requestStatus==QXHTTPRequestStatusStart||request.requestStatus==QXHTTPRequestStatusDoing||request.requestStatus==QXHTTPRequestStatusStop){

            [task cancel];

            request.requestStatus=QXHTTPRequestStatusNone;

            if(request.cancelBlock){

                request.cancelBlock(YES);

            }

            }

            

        }

        

    }

}

-(void)cancelAllRequests{

    for(NSString* tagin [self.requestsDictionaryallKeys]){

        [selfcancelRequestByTag:tag];

    }

}


-(void)resumeTaskByTag:(NSString *)tag{

    QXBaseRequest *request=[self.requestsDictionaryvalueForKey:tag];

    if(request){

        NSURLSessionTask *task=[_taskDicvalueForKey:tag];

        if(task&&[request.requestPathisEqualToString:[task taskDescription]]){

            if(request.requestStatus!=QXHTTPRequestStatusStart||request.requestStatus!=QXHTTPRequestStatusDoing){

                [task resume];

                request.requestStatus=QXHTTPRequestStatusStart;

            }

            

        }

        

    }

}


-(void)resumeAllTasks{

    for(NSString* tagin [self.requestsDictionaryallKeys]){

        [selfresumeTaskByTag:tag];

    }

}


-(void)clearAllRequest{

    if(_requestsDictionary){

        [_requestsDictionaryremoveAllObjects];

    }

    if(_taskDic){

        [_taskDicremoveAllObjects];

    }

}

@end


三,AFNetWorking

         AFNetworking:https://github.com/AFNetworking/AFNetworking

   他的核心类对比NSURLSession:

AFURLSessionManager和AFHTTPSessionManager对应NSURLSession但是功能更强大,请求的时候可以指定请求类型,回调的时候有NSProgress等,它返回的也是NSURLSessionTask对应几个子类,

AFNetWorking还有两个辅助的牛奔类:

1,AFURLRequestSerialization:封装请求类得到NSMutableURLRequest,需要url NSDictionary类型的参数,还有指定请求方法类型(GET,POST等),其实我们使用的时候都是使用它对应的子类,比如AFHTTPRequestSerialization,AFJSONRequestSerialization ,AFPropertyListRequestSerialization等


2,AFURLResoponseSerialization,用来指定解析的类型和验证数据的合法性(validateResponse),我们使用的时候也是使用它对应的子类,初始化的时候指给NSURLSessionManager就好,

        _urlSessionManager.responseSerializer=[AFJSONResponseSerializerserializer];

还有:AFHTTPResponseSerialization,AFXMLParserResponseSerialization等,示例代码如下:

@interface QXAFNetworkTools()

@property(nonatomic,strong)AFURLSessionManager *urlSessionManager;

@property(nonatomic,strong)NSString *baseUrl;

@end

@implementation QXAFNetworkTools

-(instancetype)init{

    if(self=[superinit]){

    NSURLSessionConfiguration *config=[NSURLSessionConfigurationdefaultSessionConfiguration];

        //设置Header

    [config setHTTPAdditionalHeaders:@{@"User-Agent":@"qx&wr",@"Deveice":@"Android",@"Version":@"1.1.1"}];

        //设置缓存大小

    NSURLCache *urlCache=[[NSURLCachealloc]initWithMemoryCapacity:16*1024*1024diskCapacity:60*1024*1024diskPath:nil];

    [config setURLCache:urlCache];

    

        _urlSessionManager=[[AFURLSessionManageralloc]initWithSessionConfiguration:config];

        //设置返回解析方式有好多种看源码

        _urlSessionManager.responseSerializer=[AFJSONResponseSerializerserializer];

        _baseUrl=@"";

        returnself;

    

    }else{

        returnnil;

    }

    

}

-(void)startRequest:(QXBaseRequest *)request{

    if(request){

        request.requestStatus=QXHTTPRequestStatusStart;

        NSMutableURLRequest *urlRequest;

            

            if(request.httpMethod){

                

                QXHTTPMethod method=request.httpMethod;

                NSString *reqMethod;

                

                switch (method) {

                    caseQXHTTPMethodGet:

                        reqMethod=@"GET";

                        break;

                    caseQXHTTPMethodPost:

                        reqMethod=@"POST";

                        break;

                    default:

                        reqMethod=@"GET";

                        break;

                }

                urlRequest=[[AFHTTPRequestSerializerserializer] requestWithMethod:reqMethodURLString:[_baseUrlstringByAppendingPathComponent:request.requestPath]parameters:request.paramsDictionaryerror:nil];

                NSURLSessionTask *task=[selfcreateURLSessionTask:request nsRequest:urlRequest];

                if(request.requestTag){

//                    [task setTaskDescription:request.requestPath];

//                    [_taskDic setObject:task forKey:request.requestTag];

//                    

//                    [self.requestsDictionary setObject:request forKey:request.requestTag];

                    

                }

                [task resume];

                request.requestStatus=QXHTTPRequestStatusDoing;

            }

            

        }

}


-(NSURLSessionTask*)createURLSessionTask:(QXBaseRequest*)request nsRequest:(NSMutableURLRequest*) nsRequest{

    NSURLSessionTask * task=nil;

    QXHTTPReqeustType requestType=request.requestType;

    if(requestType==QXHTTPReqeustTypeData){

        task=[_urlSessionManagerdataTaskWithRequest:nsRequest uploadProgress:nildownloadProgress:nilcompletionHandler:^(NSURLResponse *response,id responseObject,NSError *error){

        

        }];

        

    }elseif(requestType==QXHTTPReqeustTypeUpLoadFiles){

        

        task=[_urlSessionManageruploadTaskWithStreamedRequest:nsRequestprogress:nilcompletionHandler:^(NSURLResponse *_Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {

            

        }];

    }elseif(requestType==QXHTTPReqeustTypeDownLoadFiles){

        task=[_urlSessionManagerdownloadTaskWithRequest:nsRequestprogress:nildestination:^NSURL *_Nonnull(NSURL *_Nonnull targetPath, NSURLResponse *_Nonnull response) {

            return targetPath;

        } completionHandler:^(NSURLResponse *_Nonnull response, NSURL *_Nullable filePath, NSError *_Nullable error) {

            

        }];

        

    }

    

    return task;

}


@end




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值