您的当前位置:首页iOS开发-使用NSURLSession封装网络请求

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

2024-12-14 来源:哗拓教育

原理:定义接口通过传入网络地址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
显示全文