大家好,我是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),对于OC来说是一个新词,但不是新的概念,不是新的东西。学过Javascript的小伙伴对闭包应该不陌生吧~学过PHP的应该也不陌生,在PHP5.3版本以后也支持闭包, 也就是OC中所提到的Block。
现在对我们的request函数进行修改,LyNetWork.m代码如下:
+(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中的函数调用,代码修改后如下:
- (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); }]; }
测试结果依然返回succeed,测试结果正确
GET 方法下,params 在经过 url encode 之后直接附在 URL 末尾发送给服务器
类似于这个样子 GET /foo.php?first_name=John&last_name=Doe&action=Submit HTTP/1.1
修改我们的requestMethod方法,将其进行一下更改,引入parameters参数
+(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;
我们从AFNetworking中借鉴一下他的处理方案(其实这里本人就是模仿编写罢了)
我们新建一个类起名为LYURLRequestSerialization,在LYURLRequestSerialization.h添加一下方法
+(NSString *)LYQueryStringFromParameters:(NSDictionary *)parameters;
进入我们的LYURLRequestSerialization.m文件中,添加以下代码:
#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的情况,我们处理这种问题的一个思想就是递归。从最里面开始处理。
然后我们需要测试一下
为了进行测试我又重新更改了接口,提供了参数处理的能力,以下是新的接口:
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中进行测试,测试代码如下:
- (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); }]; }
ok返回结果为LastDays,成功添加入动态的动态的HTTP参数(parameters)的功能。
Tagged withiOS开发