在单独的静态方法中访问 NSURLSessionTasks 的委托 class
Accessing delegate of NSURLSessionTasks wrapped in static method in separate class
我为我的应用编写了一个单独的 Web 服务 class - WebServices.m。
其中,我有几个静态方法,如setUserInput()、getUserProfile()、registerNewUser()、logOutofAccount()。在这些方法中,我包含了各种 NSURLRequests 和 NSURLSession 任务,它们成功地到达了我服务器的端点。
我可以轻松地在各种 ViewController 中调用这些静态方法 -
我只是做 [WebServices registerNewUser]。问题是,现在我想做以下事情:
- 从任务中访问响应项
- 任务完成后转到新的Viewcontroller
我一直在使用每个 completionHandler: 中的完成块,但我假设我想做的是,我需要改用委托?如果是这样,
- 如果我在其他 classes 中使用静态方法,我该如何访问委托?
- 每个委托如何区分调用它们的不同任务?
示例将不胜感激,因为我对这一切还很陌生,而且我在 Whosebug 上找不到任何相关内容。
谢谢!
编辑:
WebServices.m 中带有完成处理程序的静态方法示例。
+(void)logOutAccount{
// 1
NSURL *url = [NSURL URLWithString:@"https://mywebsite.com/logout/"];
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.HTTPAdditionalHeaders = @{@"Authorization": @"Token 123456678809203490249019203"};
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig];
// 2
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPMethod = @"POST";
// 3
NSDictionary *dictionary = @{};
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary
options:kNilOptions error:&error];
if(!error){
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
fromData:data completionHandler:^(NSData *data,NSURLResponse *response,NSError *error) {
// Handle response here
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSLog(@"%i",httpResponse.statusCode);
}];
// 5
[uploadTask resume];
}
}
在 ViewController.m viewDidLoad() 中,我只是调用 [WebServices logOutAccount]。但是如何访问 completionHandler 的 NSURLResponse 呢?我应该使用代表吗?这就是为什么我在上面问我的问题:)
- 完成块
如URL Session Programming Guide所述
Note: Completion callbacks are primarily intended as an alternative to using a custom delegate. If you create a task using a method that takes a completion callback, the delegate methods for response and data delivery are not called.
因此,在您的情况下使用完成块是可以的,但是,
问题 #1: 您的代码不会将回调传递给调用者(例如 ViewController)。
在您的网络服务中 header:
typedef void (^WebServicesCompletionHandler)(id responseObject, NSError *error);
+ (void)logOutAccountWithCompletionHandler:(WebServicesCompletionHandler)completionBlock;
这个方法,他们都能用
问题 #2: 您使用 NSURLSessionUploadTask
作为 API(注销),不应将任何数据上传到服务器。同样,我不知道您的服务器 API,但我宁愿使用 NSURLSessionDataTask
来处理此 API。
NSURLSessionDataTask* dataTask =
[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
// process response, data and error
}
[dataTask resume];
问题 #3: 您的代码实际上并没有回调
// if the result from the API is processed from the UI, pass them in main queue
dispatch_async_main(^{
// make sure the caller has passed completionBlock
if (completionBlock) {
completionBlock(responseObject, error);
}
});
因此,完整的方法如下所示:
+ (void)logOutAccountWithCompletionHandler:(WebServicesCompletionHandler)completionBlock {
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.HTTPAdditionalHeaders = @{@"Authorization": @"Token 123456678809203490249019203"};
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig];
NSURL *url = [NSURL URLWithString:@"https://mywebsite.com/logout/"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPMethod = @"POST";
NSURLSessionDataTask* dataTask =
[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
dispatch_async_main(^{
// make sure the caller has passed completionBlock
if (completionBlock) {
completionBlock(response, error);
}
});
}];
[dataTask resume];
}
您可以从 ViewController
使用它
WebServicesCompletionHandler completionHandler;
completionHandler = ^(id response, NSError* error) {
if (error == nil) {
// process a response object
}
else {
// process an error
}
};
[WebServices logOutAccountWithCompletionHandler: completionHandler];
- 代表
使用委托涉及到更多的事情要做,所以最好找到一个完整的例子,而不是post这里。现在,我认为您可以尝试完成块解决方案。让我知道。
P.S.: 我建议您阅读一些教程以更加熟悉网络通信(例如 this one)
我为我的应用编写了一个单独的 Web 服务 class - WebServices.m。
其中,我有几个静态方法,如setUserInput()、getUserProfile()、registerNewUser()、logOutofAccount()。在这些方法中,我包含了各种 NSURLRequests 和 NSURLSession 任务,它们成功地到达了我服务器的端点。
我可以轻松地在各种 ViewController 中调用这些静态方法 - 我只是做 [WebServices registerNewUser]。问题是,现在我想做以下事情:
- 从任务中访问响应项
- 任务完成后转到新的Viewcontroller
我一直在使用每个 completionHandler: 中的完成块,但我假设我想做的是,我需要改用委托?如果是这样,
- 如果我在其他 classes 中使用静态方法,我该如何访问委托?
- 每个委托如何区分调用它们的不同任务?
示例将不胜感激,因为我对这一切还很陌生,而且我在 Whosebug 上找不到任何相关内容。
谢谢!
编辑:
WebServices.m 中带有完成处理程序的静态方法示例。
+(void)logOutAccount{
// 1
NSURL *url = [NSURL URLWithString:@"https://mywebsite.com/logout/"];
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.HTTPAdditionalHeaders = @{@"Authorization": @"Token 123456678809203490249019203"};
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig];
// 2
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPMethod = @"POST";
// 3
NSDictionary *dictionary = @{};
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary
options:kNilOptions error:&error];
if(!error){
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
fromData:data completionHandler:^(NSData *data,NSURLResponse *response,NSError *error) {
// Handle response here
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSLog(@"%i",httpResponse.statusCode);
}];
// 5
[uploadTask resume];
}
}
在 ViewController.m viewDidLoad() 中,我只是调用 [WebServices logOutAccount]。但是如何访问 completionHandler 的 NSURLResponse 呢?我应该使用代表吗?这就是为什么我在上面问我的问题:)
- 完成块
如URL Session Programming Guide所述
Note: Completion callbacks are primarily intended as an alternative to using a custom delegate. If you create a task using a method that takes a completion callback, the delegate methods for response and data delivery are not called.
因此,在您的情况下使用完成块是可以的,但是,
问题 #1: 您的代码不会将回调传递给调用者(例如 ViewController)。
在您的网络服务中 header:
typedef void (^WebServicesCompletionHandler)(id responseObject, NSError *error);
+ (void)logOutAccountWithCompletionHandler:(WebServicesCompletionHandler)completionBlock;
这个方法,他们都能用
问题 #2: 您使用 NSURLSessionUploadTask
作为 API(注销),不应将任何数据上传到服务器。同样,我不知道您的服务器 API,但我宁愿使用 NSURLSessionDataTask
来处理此 API。
NSURLSessionDataTask* dataTask =
[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
// process response, data and error
}
[dataTask resume];
问题 #3: 您的代码实际上并没有回调
// if the result from the API is processed from the UI, pass them in main queue
dispatch_async_main(^{
// make sure the caller has passed completionBlock
if (completionBlock) {
completionBlock(responseObject, error);
}
});
因此,完整的方法如下所示:
+ (void)logOutAccountWithCompletionHandler:(WebServicesCompletionHandler)completionBlock {
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.HTTPAdditionalHeaders = @{@"Authorization": @"Token 123456678809203490249019203"};
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig];
NSURL *url = [NSURL URLWithString:@"https://mywebsite.com/logout/"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPMethod = @"POST";
NSURLSessionDataTask* dataTask =
[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
dispatch_async_main(^{
// make sure the caller has passed completionBlock
if (completionBlock) {
completionBlock(response, error);
}
});
}];
[dataTask resume];
}
您可以从 ViewController
使用它WebServicesCompletionHandler completionHandler;
completionHandler = ^(id response, NSError* error) {
if (error == nil) {
// process a response object
}
else {
// process an error
}
};
[WebServices logOutAccountWithCompletionHandler: completionHandler];
- 代表
使用委托涉及到更多的事情要做,所以最好找到一个完整的例子,而不是post这里。现在,我认为您可以尝试完成块解决方案。让我知道。
P.S.: 我建议您阅读一些教程以更加熟悉网络通信(例如 this one)