基于任务,RESTful 的 HTTP 库,适用于 iOS 和 OS X。基于 ConcurrentKit 和 NSURLSession 构建。基于任务的概念可以通过以下示例更容易理解。这个库主要是将 PromiseKit 和 AFNetworking 的部分功能结合起来作为学习的例子,以学习更多关于承诺和 NSURLSession 的内容。也就是说,它使用了 AFNetworking 代码的一部分进行序列化,在 ConcurrentKit 中使用了 PromiseKit 的设计模式。您可以在以下库中查看这些代码:
DCHTTPTask *task = [DCHTTPTask GET:@"http://www.vluxe.io"];
task.thenMain(^(DCHTTPResponse *response){
NSString *str = [[NSString alloc] initWithData:response.responseObject encoding:NSUTF8StringEncoding];
NSLog(@"web request finished: %@",str);
}).catch(^(NSError *error){
NSLog(@"failed to load Request: %@",[error localizedDescription]);
});
[task start];
这里的威力不仅仅在于我们执行了一个 HTTP 请求,这可以从标准的 NSURLSession 中非常容易完成。威力在于链式、基于任务的策略。有关任务威力的更多信息,请参阅 ConcurrentKit。以下是一个更好的说明威力的示例。
DCHTTPTask *task = [DCHTTPTask GET:@"http://www.vluxe.io"];
task.then(^(DCHTTPResponse *response) {
//this is a on a background thread
NSString *str = [[NSString alloc] initWithData:response.responseObject encoding:NSUTF8StringEncoding];
//let's say we got a personal issue against h2 tags, but h3 tags are cool.
str = [str stringByReplacingOccurrencesOfString:@"</h2>" withString:@"</h3>"];
str = [str stringByReplacingOccurrencesOfString:@"<h2>" withString:@"<h3>"];
return str;
}).thenMain(^(NSString *str) {
//this is the main thread
//load modified webpage into webview...
}).catch(^(NSError *error){
NSLog(@"got an error: %@",[error localizedDescription]);
});
[task start];
Boom. 我们刚刚做了一个请求,执行了一些可能需要很长时间的操作(如本例中解析和修改一个网页),然后切换到 UI 线程以更新 UI。我们不遭受方向驱动的阻塞,并且代码保持简单、干净和完全异步。欢迎!
DCHTTPTask *task = [DCHTTPTask POST:@"http://domain.com/resource"
parameters:@{@"key": @"value",
@"auth_token": @"someToken"}];
[task.requestSerializer setValue:[NSString stringWithFormat:@"Token token=\"%@\"", API_TOKEN] forHTTPHeaderField:@"Authorization"];
task.responseSerializer = [DCJSONResponseSerializer new];
task.thenMain(^(DCHTTPResponse *response){
NSLog(@"payload: %@",response.responseObject);
NSLog(@"finished POST task");
}).catch(^(NSError *error){
NSLog(@"failed to upload file: %@",[error localizedDescription]);
});
[task start];
POST 与 GET 类似,非常简单。
NSURL *fileURL = [NSURL fileURLWithPath:@"/Users/dalton/Desktop/somefile"];
DCHTTPTask *task = [DCHTTPTask POST:@"http://domain.com/upload"
parameters:@{@"file": [DCHTTPUpload uploadWithFile:fileURL],
@"auth_token": @"someToken"}];
[task.requestSerializer setValue:[NSString stringWithFormat:@"Token token=\"%@\"", API_TOKEN] forHTTPHeaderField:@"Authorization"];
task.responseSerializer = [DCJSONResponseSerializer new];
task.thenMain(^(DCHTTPResponse *response){
NSLog(@"payload: %@",response.responseObject);
NSLog(@"finished upload task");
return nil;
}).catch(^(NSError *error){
NSLog(@"failed to upload file: %@",[error localizedDescription]);
});
[task start];
文件上传的多部分表单非常简单。简单的创建一个提供 DCHTTPUpload 对象。
DCHTTPTask *task = [DCHTTPTask GET:@"https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/ObjC_classic/FoundationObjC.pdf" parameters:nil];
task.download = YES;
//you can also set downloadUrl for custom download locations.
//task.downloadUrl = [NSURL fileURLWithPath:@"your custom path"];
[task setProgress:^(CGFloat progress) {
NSLog(@"download task progress: %f",progress);
}];
task.thenMain(^(DCHTTPResponse *response) {
NSURL *destinationURL = response.responseObject;
self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:destinationURL];
[self.documentInteractionController setDelegate:self];
[self.documentInteractionController presentPreviewAnimated:YES];
return nil;
}).catch(^(NSError *error) {
NSLog("We got an error!?!?: %@",[error localizedDescription]);
});
[task start];
我们只需几行代码就可以安排一个基于后台的任务,并在完成时得到通知。我们利用了 NSURLSession 的后台下载功能,然后在仍然处于后台状态的情况下,我们将文件复制到其新永久位置,然后跳回主线程以查看文件。我们甚至获得了可以连接到进度视图的进度通知。
NSURL *fileURL = [NSURL fileURLWithPath:@"/Users/dalton/Desktop/somefile"];
DCHTTPTask *task = [DCHTTPTask POST:@"http://domain.com/upload"
parameters:@{@"file": [DCHTTPUpload uploadWithFile:fileURL]}];
[task setProgress:^(CGFloat progress) {
NSLog(@"upload task progress: %f",progress);
}];
[task.requestSerializer setValue:[NSString stringWithFormat:@"Token token=\"%@\"", API_TOKEN] forHTTPHeaderField:@"Authorization"];
task.responseSerializer = [DCJSONResponseSerializer new];
task.thenMain(^(DCHTTPResponse *response){
NSLog(@"payload: %@",response.responseObject);
NSLog(@"finished upload task");
return nil;
}).catch(^(NSError *error){
NSLog(@"failed to upload file: %@",[error localizedDescription]);
});
[task start];
此功能会在后台上传文件。需要注意的是,NSURLSession 将后台上传限制为单个文件URL(仅后台上传),并忽略除上传文件之外的所有参数。这并不是最理想的情况,但我们也只能做自己能做的。这种限制仅存在于后台上传时,常规上传没有这个问题。
API交互在移动端非常常见。HTTPKit为你提供了支持。
DCHTTPTaskManager *manager = [DCHTTPTaskManager new];
manager.baseURL = @"http://domain.com/1/";
[manager.requestSerializer setValue:[NSString stringWithFormat:@"Token token=\"%@\"", API_TOKEN] forHTTPHeaderField:@"Authorization"];
[manager addParameter:@"someToken" forKey:@"auth_token"];
DCHTTPTask *task = [manager GET:@"users" parameters:@{@"id": @1}];
task.thenMain(^(DCHTTPResponse *response){
// do something with the JSON.
return nil;
}).catch(^(NSError *error){
NSLog(@"failed to load user request: %@",[error localizedDescription]);
});
[task start];
DCHTTPTask *otherTask = [manager POST:@"users" parameters:@{@"id": @1, @"name": @"Dalton"}];
otherTask.thenMain(^(DCHTTPResponse *response){
// do something with the JSON.
return nil;
}).catch(^(NSError *error){
NSLog(@"failed to load user request: %@",[error localizedDescription]);
});
[otherTask start];
任务将创建,并包含共享数据(基础URL、header值、auth_token参数等)。DCHTTPTaskManager默认使用JSON序列化作为其序列化格式。
每个请求都可以有一个请求和响应序列化器。这些主要是序列化或编码/解码请求数据和响应。它们使用非常简单。默认使用HTTPRequestSerializer作为请求序列化器,并且默认没有设置响应序列化器(意味着将返回NSData对象)。
DCHTTPTask *task = [manager POST:@"users" parameters:@{@"id": @1}];
//set both to be JSON serializer
task.requestSerializer = [DCJSONRequestSerializer new];
task.responseSerializer = [DCJSONResponseSerializer new];
您还可以为不同的内容类型设置多个响应序列化器。
[task setResponseSerializer:[DCJSONResponseSerializer new] forContentType:@"application/json"];
JSONResponse序列化器将仅用于该内容类型,而responseSerializer将用于所有其他内容类型。
内置了针对HEAD、DELETE、GET、POST、PUT等方法的处理方法。您不必仅限于这些HTTP方法(动词),但它们是最常用的。您可以像这样简单地在HTTP方法上进行切换
DCHTTPTask *task = [DCHTTPTask GET:@"http://www.vluxe.io"];
task.HTTPMethod = @"OTHERMETHOD";
task.thenMain(^(DCHTTPResponse *response){
NSString *str = [[NSString alloc] initWithData:response.responseObject encoding:NSUTF8StringEncoding];
NSLog(@"web request finished: %@",str);
return nil;
}).catch(^(NSError *error){
NSLog(@"failed to load Request: %@",[error localizedDescription]);
});
[task start];
推荐通过CocoaPods包管理器安装HTTPKit,因为它提供灵活的依赖管理,并且安装过程简单易行。
使用CocoaPods
如果没有安装CocoaPods,请先安装它
$ [sudo] gem install cocoapods
$ pod setup
切换到您的Xcode项目目录,创建和编辑您的Podfile,并添加HTTPKit
$ cd /path/to/MyProject
$ touch Podfile
$ edit Podfile
platform :ios, '7.0'
#or platform :osx, '10.9'
pod 'HTTPKit'
将HTTPKit安装到项目中
$ pod install
从.xcworkspace文件(而不是常规的项目文件)中打开您的项目到Xcode
HTTPKit需要至少iOS 7/OSX 10.9或更高版本。
HTTPKit采用Apache许可证。