【问题标题】:How do I handle asynchronous processes in iOS ViewControllers?如何在 iOS ViewControllers 中处理异步进程?
【发布时间】:2012-06-15 07:13:59
【问题描述】:

我目前正在开发一个应用程序,它允许用户使用 HTTP 请求(JSON 格式)向远程服务器进行身份验证。

我创建了一个单独的类来处理 API 请求,因为我将在整个应用程序中做很多事情。

APIRequest 中最神奇的方法是:

-(void)send
{
    self.isLoading = YES;
    request_obj = [[self httpClient] requestWithMethod:method path:extendedResourcePath parameters:params];
    AFJSONRequestOperation *operation = [AFJSONRequestOperation 
                                         JSONRequestOperationWithRequest:request_obj 
                                        success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                                            self.response = [[APIResponse alloc] initWithResponse:response andJSON:JSON];
                                            self.isLoading = NO;
                                        } 
                                        failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
                                            self.isLoading = NO;
                                        }];

    // queue is defined elsewhere in the class as an instance of NSOperationQueue
    [queue addOperation:operation];
}

在我的控制器中,当按下按钮时,我会调用:

// set the session params from the form values
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: 
                        self.usernameField.text, @"session[username]", 
                        self.passwordField.text, @"session[password]", nil];

// create a new API request object
api_request = [[APIRequest alloc] initWithReourcePath:@"sessions" andMethod:HTTPMethodPOST andParams:params];

// send the request
[api_request send];

我似乎无法解决的是如何通知控制器请求已完成。

我在 APIRequest 上有一个名为 isLoading 的属性,只要请求仍在发生,它就会显示为“YES”。所以,我知道我可以通过询问来检查 api_request 是否完成。

我想不出控制器会在几秒钟后响应任何事件以询问 api_request 是否完成。

任何人都可以在这里提出一个好的方法吗?

【问题讨论】:

    标签: objective-c ios5 xcode4.2 afnetworking


    【解决方案1】:

    不要使用这些全局布尔值来跟踪连接状态,而是将 -send: 方法签名更改为接受块并在完成时调用块的方法。我经常这样做。我从事的一个项目的一个例子:

    - (void)getDealsWithSuccess:(void (^)(NSArray *deals))success failure:(void (^)(NSError *error))failure
    {
        // lots of OAuth + Request creation code here ...
    
        AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request 
         success:^ (NSURLRequest *request, NSURLResponse *response, id json) {
            NSLog(@"%@", json);
    
            // handle result here, e.g. 
            // I convert the json to a array with custom objects here ...
    
            if (success) 
                success(deals);
    
        } failure:^ (NSURLRequest *request, NSURLResponse *response, NSError *error, id json) {
            NSLog(@"%@", error);
    
            // handle error here ..
    
            if (failure)
                failure(error);
        }];
    
        [operation start];
    }
    

    【讨论】:

    • 我今天早些时候发现了这种方法——我更喜欢它。谢谢:)
    【解决方案2】:

    两个快速解决方案:

    1. 使用NSNotificationCenter(在 iOS 上可用)发布 完成处理块中的消息。您的控制器可以 订阅适当的消息并收到有关操作状态的通知。
    2. 子类 AFJSONRequestOperation 并添加“委托”属性。将 [[self delegate] performSelectorOnMainThread:@selector(operationSucceded:) withObject:self waitUntilDone:NO]; 之类的内容添加到处理块中。

    我个人更喜欢第一种方式,因为我尽量避免在这种简单的情况下进行子类化。

    【讨论】:

      【解决方案3】:

      我认为另一种方法是使用KVO

      // Add observer for your key
      [api_request addObserver:self forKeyPath:@"isLoading" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOption) context:NULL];
      
      // Add below method into your implementation
      - (void)observeValueForKeyPath:(NSString *)keyPath  
                            ofObject:(id)object  
                              change:(NSDictionary *)change  
                             context:(void *)context
      {
          // put your stuffs here...
      }
      

      【讨论】:

        【解决方案4】:

        两天前我问了同样的问题......希望我先看到这个。我将尝试两种方法来实现这一点。一,在我的 Services 类中创建一个委托,它将触发我的 ViewController 中的方法(See this answer)...

        或者二,创建一个包含回调块的方法......类似于这个问题的答案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-11-20
          • 2015-11-23
          • 2016-04-11
          • 1970-01-01
          • 2021-02-26
          • 1970-01-01
          • 2018-12-10
          • 1970-01-01
          相关资源
          最近更新 更多