我为我的应用程序写了一个单独的WebServices类 - WebServices.m。
在其中,我有几个静态方法,如setUserInput(),getUserProfile(),registerNewUser(),logOutofAccount()。在这些方法中,我包括各种NSURLRequests和NSURLSession任务,这些任务成功命中了我的服务器端点。
我可以在各种ViewControllers中轻松调用这些静态方法 - 我只是做[WebServices registerNewUser]。问题是,现在我想做以下事情:
我一直在每个completionHandler中使用完成块:但我假设我正在尝试做什么,我需要使用委托代替?如果是的话,
示例将非常受欢迎,因为我对这一切都很陌生,我在StackOverflow上找不到任何相关内容。
谢谢!
修改
带有完成处理程序的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呢?我应该使用代表吗?这就是为什么我在上面提出我的问题:)
答案 0 :(得分:1)
作为URL Session Programming Guide州
注意:完成回调主要用作使用自定义委托的替代方法。如果使用执行完成回调的方法创建任务,则不会调用响应和数据传递的委托方法。
因此,在您的情况下,可以使用完成块,
问题#1:您的代码未将回调传递给调用者(例如ViewController)。
在WebServices的标题中:
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];
使用委托涉及更多的事情,所以最好找到一个完整的例子,而不是在这里发布。目前,我认为您可以尝试完成块解决方案。让我知道。
P.S。:我建议您通过几个教程来熟悉网络通信(例如this one)