转载

一步一步搭建自己的iOS网络请求库(二)--封装接口

一步一步搭建自己的iOS网络请求库(二)

大家好,我是LastDay,上一次分享了简单体验并且测试下一下NSURLSession。

我的博客地址:http://lastday.github.io

进行简单的封装

我们接下来将要加入动态的动态的HTTP参数(parameters)的功能,之后封装出我们自己的接口。

首先呢,我们先来对上一次的代码进行一次简单的封装,建立一个新的类LyNetWork,继承于NSObject类 。新建一个静态的request方法。将请求方式和URL传入

代码如下:

+(void)request :(NSString *)method URL:(NSString *)URL{     NSURL *url = [NSURL URLWithString:URL];     NSURLSession *session = [NSURLSession sharedSession];     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];     request.HTTPMethod = method;     NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data,NSURLResponse *reponse,NSError *error){              //NSdata转String         NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];         NSLog(@"%@",string);     }];     [task resume];  }  

OK

让我们在ViewController中进行一下测试,代码如下:

 @IBAction func mainButtonBeTapped(sender: AnyObject) {     [LyNetWork request:@"GET" URL:@"http://cityuit.sinaapp.com/1.php"]; }  

接下来运行一下:OK 依然显示我们正确的测试结果:succeed

使用Block处理请求返回值

简单的介绍下闭包(block),对于OC来说是一个新词,但不是新的概念,不是新的东西。学过Javascript的小伙伴对闭包应该不陌生吧~学过PHP的应该也不陌生,在PHP5.3版本以后也支持闭包, 也就是OC中所提到的Block。

现在对我们的request函数进行修改,LyNetWork.m代码如下:

一步一步搭建自己的iOS网络请求库(二)--封装接口

+(void)requestMethod:(NSString *)method                  URL:(NSString *)URL              success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success              failure:(void (^)(NSError *__nullable error))failure {     NSURL *url = [NSURL URLWithString:URL];     NSURLSession *session = [NSURLSession sharedSession];     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];     request.HTTPMethod = method;     NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data,NSURLResponse *response,NSError *error){         if (error) {             failure(error);         }else{             if (success) {                 success(data,response);             }         }              }];          [task resume]; }  

接下来修改ViewController中的函数调用,代码修改后如下:

一步一步搭建自己的iOS网络请求库(二)--封装接口

 - (IBAction)test:(id)sender {     [LyNetWork requestMethod:@"GET"                          URL:@"http://cityuit.sinaapp.com/1.php"                      success:^(NSData *data,NSURLResponse *response){                          NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];                          NSLog(@"%@",string);                      }                      failure:^(NSError *error){                          NSLog(@"%@",error);                      }]; }  

一步一步搭建自己的iOS网络请求库(二)--封装接口

测试结果依然返回succeed,测试结果正确

接下来进行我们最难处理的地方,增加parameters处理能力

我们先来处理GET方法吧

GET 方法下,params 在经过 url encode 之后直接附在 URL 末尾发送给服务器

类似于这个样子 GET /foo.php?first_name=John&last_name=Doe&action=Submit HTTP/1.1

修改我们的requestMethod方法,将其进行一下更改,引入parameters参数

一步一步搭建自己的iOS网络请求库(二)--封装接口

+(void)requestMethod:(nullable NSString *)method                  URL:(nullable NSString *)URL             parameters:(nullable id) parameters              success:(nullable void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success              failure:(nullable void (^)(NSError *__nullable error))failure;  

接下来就该处理我们的parameters参数了

我们从AFNetworking中借鉴一下他的处理方案(其实这里本人就是模仿编写罢了)

我们新建一个类起名为LYURLRequestSerialization,在LYURLRequestSerialization.h添加一下方法

+(NSString *)LYQueryStringFromParameters:(NSDictionary *)parameters;  

进入我们的LYURLRequestSerialization.m文件中,添加以下代码:

一步一步搭建自己的iOS网络请求库(二)--封装接口

 #import "LYURLRequestSerialization.h"  @interface LYURLRequestSerialization()  @property (readwrite, nonatomic, strong) id  value; @property (readwrite, nonatomic, strong) id  field;   @end  @implementation LYURLRequestSerialization    - (id)initWithField:(id)field value:(id)value {     self = [super init];     if (!self) {         return nil;     }          self.field = field;     self.value = value;          return self; }  #pragma mark -  FOUNDATION_EXPORT NSArray * LYQueryStringPairsFromDictionary(NSDictionary *dictionary); FOUNDATION_EXPORT NSArray * LYQueryStringPairsFromKeyAndValue(NSString *key, id value);  +(NSString *)LYQueryStringFromParameters:(NSDictionary *)parameters {     NSMutableArray *mutablePairs = [NSMutableArray array];     for (LYURLRequestSerialization *pair in LYQueryStringPairsFromDictionary(parameters)) {                  [mutablePairs addObject:[pair URLEncodedStringValue]];     }          return [mutablePairs componentsJoinedByString:@"&"]; }    NSArray * LYQueryStringPairsFromDictionary(NSDictionary *dictionary) {     return LYQueryStringPairsFromKeyAndValue(nil, dictionary); }    NSArray * LYQueryStringPairsFromKeyAndValue(NSString *key, id value) {     NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];          NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];          if ([value isKindOfClass:[NSDictionary class]]) {         NSDictionary *dictionary = value;         for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {             id nestedValue = dictionary[nestedKey];             if (nestedValue) {                 [mutableQueryStringComponents addObjectsFromArray:LYQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];             }         }     } else if ([value isKindOfClass:[NSArray class]]) {         NSArray *array = value;         for (id nestedValue in array) {             [mutableQueryStringComponents addObjectsFromArray:LYQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];         }     } else if ([value isKindOfClass:[NSSet class]]) {         NSSet *set = value;         for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {             [mutableQueryStringComponents addObjectsFromArray:LYQueryStringPairsFromKeyAndValue(key, obj)];         }     } else {         [mutableQueryStringComponents addObject:[[LYURLRequestSerialization alloc] initWithField:key value:value]];     }          return mutableQueryStringComponents; }   static NSString * LYPercentEscapedStringFromString(NSString *string) {     static NSString * const kLYCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4     static NSString * const kLYCharactersSubDelimitersToEncode = @"!$&'()*+,;=";          NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];     [allowedCharacterSet removeCharactersInString:[kLYCharactersGeneralDelimitersToEncode stringByAppendingString:kLYCharactersSubDelimitersToEncode]];               static NSUInteger const batchSize = 50;          NSUInteger index = 0;     NSMutableString *escaped = @"".mutableCopy;          while (index < string.length) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wgnu"         NSUInteger length = MIN(string.length - index, batchSize); #pragma GCC diagnostic pop         NSRange range = NSMakeRange(index, length);                  range = [string rangeOfComposedCharacterSequencesForRange:range];                  NSString *substring = [string substringWithRange:range];         NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];         [escaped appendString:encoded];                  index += range.length;     }          return escaped; }  - (NSString *)URLEncodedStringValue {     if (!self.value || [self.value isEqual:[NSNull null]]) {         return LYPercentEscapedStringFromString([self.field description]);     } else {         return [NSString stringWithFormat:@"%@=%@", LYPercentEscapedStringFromString([self.field description]), LYPercentEscapedStringFromString([self.value description])];     } }  @end   

简单的说一下吧,以上的方法都是为了处理传入的NSDictonary参数,因为我们在使用的时候为了方便我们传入动态的parameters,所以他的的格式是这样的:

id parmenters = @{                   @"value":@"LastDays",                  }; 

将它处理后我们希望得到的样式应该是这样,对吧?

http:URL.php?value=LastDays  

这个参数是一个动态的,我们不能确定里面到底有几组参数,而且还需要考虑的一个问题就是NSDictonary中嵌套NSDictonary的情况,我们处理这种问题的一个思想就是递归。从最里面开始处理。

OK,这样我们就实现了parameters处理能力

然后我们需要测试一下

为了进行测试我又重新更改了接口,提供了参数处理的能力,以下是新的接口:

http://cityuit.sinaapp.com/1.php  value=将要返回的值 

更改下requestMethod方法

 +(void)requestMethod:(NSString *)method                  URL:(NSString *)URL           parameters:(id) parameters              success:(void (^)(NSData *__nullable data,NSURLResponse * __nullable response))success              failure:(void (^)(NSError *__nullable error))failure {     NSString *newURL;     if ([method isEqual:@"GET"]) {         newURL = [[URL stringByAppendingString:@"?"] stringByAppendingString: [LYURLRequestSerialization LYQueryStringFromParameters:parameters]];                  NSLog(@"%@",newURL);     }          NSURL *url = [NSURL URLWithString:newURL];     NSURLSession *session = [NSURLSession sharedSession];     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];     request.HTTPMethod = method;     NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * data,NSURLResponse *response,NSError *error){         if (error) {             failure(error);         }else{             if (success) {                 success(data,response);             }         }     }];     [task resume]; }  

其中变化的地方:

if ([method isEqual:@"GET"]) {         newURL = [[URL stringByAppendingString:@"?"] stringByAppendingString: [LYURLRequestSerialization LYQueryStringFromParameters:parameters]];         NSLog(@"%@",newURL);     }  

以上代码的意思就是判断一下是否未GET请求,如果是的话将处理后的parameters加到尾部,以刚才的参数为例子,处理后的newURL为:http://cityuit.sinaapp.com/1.php?value=LastDays

也就是说返回值为LastDays

到ViewController.m中进行测试,测试代码如下:

一步一步搭建自己的iOS网络请求库(二)--封装接口

- (IBAction)test:(id)sender {          id parmenters = @{                       @"value":@"LastDays",                       };     [LyNetWork requestMethod:@"GET"                          URL:@"http://cityuit.sinaapp.com/1.php"                   parameters:parmenters                      success:^(NSData *data,NSURLResponse *response){                          NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];                          NSLog(@"%@",string);                      }                      failure:^(NSError *error){                          NSLog(@"%@",error);                      }]; } 

一步一步搭建自己的iOS网络请求库(二)--封装接口

ok返回结果为LastDays,成功添加入动态的动态的HTTP参数(parameters)的功能。

下一次将会分享POST请求的处理。

Tagged withiOS开发

正文到此结束
Loading...