在单独的类

时间:2016-01-28 12:02:33

标签: ios objective-c nsurlconnection nsurlsession

我为我的应用程序写了一个单独的WebServices类 - WebServices.m。

在其中,我有几个静态方法,如setUserInput(),getUserProfile(),registerNewUser(),logOutofAccount()。在这些方法中,我包括各种NSURLRequests和NSURLSession任务,这些任务成功命中了我的服务器端点。

我可以在各种ViewControllers中轻松调用这些静态方法 - 我只是做[WebServices registerNewUser]。问题是,现在我想做以下事情:

  1. 从任务
  2. 访问响应项
  3. 完成任务后,转到新的Viewcontroller
  4. 我一直在每个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呢?我应该使用代表吗?这就是为什么我在上面提出我的问题:)

1 个答案:

答案 0 :(得分:1)

  1. 完成块
  2. 作为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];
    
    1. 代表
    2. 使用委托涉及更多的事情,所以最好找到一个完整的例子,而不是在这里发布。目前,我认为您可以尝试完成块解决方案。让我知道。

      P.S。:我建议您通过几个教程来熟悉网络通信(例如this one