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

http://www.tuicool.com/articles/mQj2AfF


原文  http://lastday.github.io/ioshttplibrary/HttpLibrary2/

主题 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代码如下:

+(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,测试结果正确

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

我们先来处理GET方法吧

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;

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

我们从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的情况,我们处理这种问题的一个思想就是递归。从最里面开始处理。

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中进行测试,测试代码如下:

- (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)的功能。

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

推荐阅读更多精彩内容