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

前言:今天小编的一个朋友的项目使用到了聚合数据和阿凡达数据的银行卡查询的接口,而使用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上传,如果还有哪个地方不清楚的,随时都可以问我,我会看到第一时间回复你。最后,还是希望能够帮助到有需要的朋友们,愿同是程序猿的我们能够共同学习,共同进步,愿我们在开发的道路上越走越远!希望大家能够喜欢!谢谢!

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

推荐阅读更多精彩内容