美文网首页iOS技术分享AFNetworkingiOS开发
iOS开发-使用NSURLSession封装网络请求

iOS开发-使用NSURLSession封装网络请求

作者: it_hao528 | 来源:发表于2016-11-06 00:37 被阅读503次

    前言:今天小编的一个朋友的项目使用到了聚合数据和阿凡达数据的银行卡查询的接口,而使用AFNetworking请求每次都出错,具体原因暂未知(已知使用网络接口测试软件测试接口没问题且安卓端请求没有问题)。于是,小编和我朋友相互讨论了好久,最后决定尝试使用iOS原生的网络请求类NSURLConnection,结果数据请求成功了,当时好激动。小编本着好东西大家一起来分享的精神将该网络请求进行了封装,由于在iOS9.0之后NSURLConnection已经过时了,出现了最新的NSURLSession,为了大家能够长久的使用,故小编使用NSURLSession进行了网络请求的封装。

    原理:定义接口通过传入网络地址url和地址参数parameters来进行网络请求的调用,同时将请求的结果以代理的方式来进行回调。

    下面就由小编来给大家详细介绍:

    首先,创建一个继承于NSObject的类,在.h文件中设置代理协议及方法,并声明代理和接口方法。代码如下:

    #import <Foundation/Foundation.h>
    
    @protocol RHURLRequestDelegate;
    @interface RHURLRequest : NSObject
    
    //代理属性
    @property (nonatomic, weak)id<RHURLRequestDelegate> delegate;
    
    //POST请求接口方法
    - (void)startPOSTRequestWithUrl:(NSString *)url parameters:(NSDictionary *)parameters;
    //GET请求接口方法
    - (void)startGETRequestWithUrl:(NSString *)url parameters:(NSDictionary *)parameters;
    @end
    /代理协议及方法
    @protocol RHURLRequestDelegate <NSObject>
    
    //请求成功回调的方法,参数为请求得到的解析之后的数据
    - (void)requestDidSuccessData:(id)data;
    //请求失败回调的方法,参数为请求失败的错误信息
    - (void)requestDidFailedError:(NSError *)error;
    
    @end
    

    接着就是在.m文件中实现声明的接口方法,具体代码及注释如下:

    #import "RHURLRequest.h"
    
    @implementation RHURLRequest
    
    //POST请求   url为传入的网址, parameters为请求的参数以字典形式传入
    - (void)startPOSTRequestWithUrl:(NSString *)url parameters:(NSDictionary *)parameters {
        
        // 将参数添加在请求体中
        NSMutableString * str = [NSMutableString string];
        //参数处理
        for (NSString * key in parameters) {
            
            [str appendFormat:@"%@=%@&", key, parameters[key]];
        }
    
        // 创建请求体
        NSData * body = [str dataUsingEncoding:NSUTF8StringEncoding];
    
        // 创建URL
        NSURL * URL = [NSURL URLWithString:url];
        
        // 创建可变请求对象
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
    
        // 设置请求方法
        [request setHTTPMethod:@"POST"];
        
        // 设置请求体
        [request setHTTPBody:body];
        
        // 实例化网络会话.
        NSURLSession *session = [NSURLSession sharedSession];
        
        // 根据请求对象创建请求任务
        NSURLSessionDataTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
            if (!error) {
                
                //请求成功  对请求的数据做初步的json解析
                id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                //回调代理方法,并传入请求结果
                if ([self.delegate respondsToSelector:@selector(requestDidSuccessData:)]) {
                    
                    [self.delegate requestDidSuccessData:object];
                }
            }else {
                
                //请求失败   回调代理方法,并传入错误信息
                if ([self.delegate respondsToSelector:@selector(requestDidFailedError:)]) {
                    
                    [self.delegate requestDidFailedError:error];
                }
            }
        }];
        
        // 开启任务.  //这一步很关键,如果没有这一步,请求任务不会执行
        [task resume];
    }
    
    //GET请求  url为传入的网址, parameters为请求的参数以字典形式传入
    - (void)startGETRequestWithUrl:(NSString *)url parameters:(NSDictionary *)parameters {
    
        //GET请求需要将参数拼接在url后面
        //网络接口和参数 以“?”分隔. 参数和参数之间以“&”符号分隔。
        // 拼接url及参数
        NSMutableString * str = [NSMutableString string];
        
        [str appendString:url];
    
        //当有参数时将参数拼接上去(小编在此做的是url没有拼接参数情况下,如果url已经拼接了参数,这里还传入了一些参数,那么此处的判断需要更改,具体的大家可以来实现)
        if (parameters.count > 0) {
    
            //小编在此对url时候以"?"结尾做了判断,有的话就不需要再拼接"?"
            if (![str hasSuffix:@"?"]) {
                
                [str appendString:@"?"];
            }
    
            //拼接参数
            for (NSString * key in parameters) {
                
                [str appendFormat:@"%@=%@&", key, parameters[key]];
            }
    
            //注意最后一个"&"符号需要去掉
            [str deleteCharactersInRange:NSMakeRange(str.length - 1, 1)];
        }
    
        // 设置URL
        NSURL * URL = [NSURL URLWithString:str];
        
        // 实例化网络会话.
        NSURLSession * session = [NSURLSession sharedSession];
    
        //根据URL创建请求任务
        NSURLSessionDataTask * task = [session dataTaskWithURL:URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
            if (!error) {
                
                //请求成功  对请求的数据做初步的json解析
                id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                //回调代理方法,并传入请求结果
                if ([self.delegate respondsToSelector:@selector(requestDidSuccessData:)]) {
                    
                    [self.delegate requestDidSuccessData:object];
                }
            }else {
                
                //请求失败  回调代理方法,并传入错误信息
                if ([self.delegate respondsToSelector:@selector(requestDidFailedError:)]) {
                    
                    [self.delegate requestDidFailedError:error];
                }
            }
        }];
        
        // 开启任务.  //这一步很关键,如果没有这一步,请求任务不会执行
        [task resume];
    }
    @end
    

    OK!到此我们就封装好了一个简单的网络请求的类,能够实现POST和GET请求,请求速度还是很快的。如果平时工作中遇到了AFNetworking请求总是出错的问题的时候,不妨尝试一个该类,说不定会有给我们惊喜的哦!

    下面小编再来给大家简单说一下如何使用,虽然小编知道大部分的猿友们都很清楚,但还请包涵小编在此多唠叨几句:

    #import "ViewController.h"
    #import "RHURLRequest.h"
    
    @interface ViewController () <RHURLRequestDelegate>
    
    @property (nonatomic, strong) RHURLRequest * request;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        //由于没有现成可公开的接口来测试,所以这里就留给大家来填写测试了
        //传入相应的参数开始POST请求
        [self.request startPOSTRequestWithUrl:@"" parameters:@{}];
    
        //传入相应的参数开始GET请求
        [self.request startGETRequestWithUrl:@"" parameters:@{}];
    }
    
    #pragma mark - request delegate
    //请求成功回调的代理方法,data为请求的json解析之后的结果
    - (void)requestDidSuccessData:(id)data {
        
        NSLog(@"%@", data);
    }
    //请求失败回调的代理方法,error为错误信息
    - (void)requestDidFailedError:(NSError *)error {
        
        NSLog(@"%@", error.localizedDescription);
    }
    
    #pragma mark - 懒加载
    
    - (RHURLRequest *)request {
        
        if (!_request) {
            
            _request = [[RHURLRequest alloc] init];
            
            _request.delegate = self;
        }
        return _request;
    }
    @end
    

    所有的代码及注释都已经很清楚了,小编就没有写demo上传,如果还有哪个地方不清楚的,随时都可以问我,我会看到第一时间回复你。最后,还是希望能够帮助到有需要的朋友们,愿同是程序猿的我们能够共同学习,共同进步,愿我们在开发的道路上越走越远!希望大家能够喜欢!谢谢!

    相关文章

      网友评论

      • 飞雪飘零丶夜孤城:我在开发中遇到的困难!我不知道如何处理!我连续10条并发,其中三路出现错误,程序崩溃!……
        it_hao528:@飞雪飘零丶夜孤城 这个找到错误解决就好了,一般没什么问题的。
      • 飞雪飘零丶夜孤城:我想问的是如果是并发请求,或者多路请求,如果其中一路出现错误,你如何处理?
        it_hao528:你好,当时由于写的比较急并没有考虑这么多,其实用代理并不是很好,回调可以改为block,这样就能很方便的一对一的对应起来,如果出现错误可以根据自己的需求做出相应的修改。

      本文标题:iOS开发-使用NSURLSession封装网络请求

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