【问题标题】:NSURLSession uploadTaskWithRequest - use block within completion handlerNSURLSession uploadTaskWithRequest - 在完成处理程序中使用块
【发布时间】:2014-04-07 04:16:56
【问题描述】:

我有一个类来管理对 api 的所有调用。 它有一个方法来管理这个,我们称之为callAPIMethod:

此方法接受 successfail 块。

在这个方法中,我调用uploadTaskWithRequest 来调用一个API。 在 uploadTaskWithRequest 完成处理程序中,我想(取决于结果)将结果传递回 successfail 块。

我遇到了一些问题。它可以工作并且保持一切都超级整洁,但是当我使用成功/失败块调用callAPIMethod 时,它会锁定 UI/MainThread,而不是像我期望的那样异步。

我应该如何实现这种模式?还是有更好的办法?

我不需要支持pre-iOS7。

谢谢

编辑:上面讨论的基本实现。

- (void)callApiMethod:(NSString *)method withData:(NSString *)requestData as:(kRequestType)requestType success:(void (^)(id responseData))success failure:(void (^)(NSString *errorDescription))failure {
    [redacted]
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session uploadTaskWithRequest:request
                                                       fromData:postData
                                              completionHandler:
                                  ^(NSData *data, NSURLResponse *response, NSError *error) {
                                      if (error) {
                                          failure(error.description);
                                      } else {
                                          NSError *jsonError;
                                          id responseData = [NSJSONSerialization
                                                             JSONObjectWithData:data
                                                             options:kNilOptions
                                                             error:&jsonError];
                                          if (jsonError) {
                                              failure(jsonError.description);
                                          } else {
                                              success(responseData);
                                          }
                                      }
                                  }];

    [task resume];
}

CallAPI 方法,使用如下(来自 UITableViewController):

[apiController callApiMethod:@"users.json?action=token"
                    withData:loginData
                          as:kRequestPOST
                     success:^(id responseData) {
                         if ([responseData isKindOfClass:[NSDictionary class]]) {
                             if ([responseData objectForKey:@"token"]) {
                                 //Store token/credentials
                             } else if ([responseData objectForKey:@"error"]) {
                                 //Error
                                 [self displayErrorMessage:[responseData objectForKey:@"error"]];
                                 return;
                             } else {
                                 //Undefined Error
                                 [self displayErrorMessage:nil];
                                 return;
                             }
                         } else {
                             //Error
                             [self displayErrorMessage:nil];
                             return;
                         }

                         //If login success

                     }
                     failure:^(NSString *errorDescription) {
                         [self displayErrorMessage:errorDescription];
                     }];

【问题讨论】:

  • 编辑添加代码。认为这是一种可以接受的方式,所以可能会做一些完全愚蠢的事情。
  • 关于调度到主线程的好点。成功后,我将一个新的视图控制器推送到导航堆栈。猜猜我也应该将它发送到主线程? displayErrorMessage 显示一个 alertView,尽管无论是否有错误,UI 都会被锁定。
  • 谢谢!正如我所想,一个愚蠢的错误。我假设如果不在主线程上它会崩溃......而不是仅仅挂起 10 多秒。

标签: objective-c objective-c-blocks nsurlsession


【解决方案1】:

您的NSURLSession 代码看起来不错。我建议添加一些断点,以便您可以确定它是否在某处死锁,如果是,在哪里。但此代码示例中的任何内容都不会显示任何此类问题。

我建议您确保将所有 UI 调用分派回主队列。这个NSURLSessionUploadTask 完成处理程序可以在后台队列中调用,但所有 UI 更新(警报、导航、UIView 控件的更新等)都必须在主队列中进行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多