【问题标题】:How to turn an asynchronous method into a synchronous method [closed]如何将异步方法转换为同步方法 [关闭]
【发布时间】:2019-12-26 18:18:32
【问题描述】:

我正在从另一个方法调用一个方法。该方法在中间退出。完成一些任务后,它会运行剩下的方法。

-(void)stateMethod{
    [self.pickerView selectRow:0 inComponent:0 animated:YES];
    lblTitle.text=@"State";
    self.stateTF.text=@"";
    self.stateTF.inputView=_pickerView;
    [self.stateTF setInputAccessoryView:toolBar];
    NSString * method=@"***************************?countryID=";
    NSString *urlString=[NSString stringWithFormat:@"%@%@%@",MAIN_URL,method,_countryId];
    NSURL *url_ac=[[NSURL alloc]initWithString:urlString];
    NSMutableURLRequest *request_ac=[[NSMutableURLRequest alloc]initWithURL:url_ac];
    [request_ac setValue:loginUser.acessTokenStr forHTTPHeaderField:@"access_token"];

   [NSURLConnection sendAsynchronousRequest:request_ac queue:[NSOperationQueue currentQueue] completionHandler:
 ^(NSURLResponse ac_response, NSData acData, NSError *connectionError) {
     if (connectionError)
     {
         NSLog(@"ERROR CONNECTING DATA FROM SERVER: %@", connectionError.localizedDescription);
     }
    else {            
    dispatch_async(dispatch_get_main_queue(), ^{
             NSString *responseString = [[NSString alloc] initWithData:acData encoding:NSUTF8StringEncoding];
             [self parseStateListResult:acData];
         });
     }
 }];  
}

我想要在调用状态方法时得到响应。基于状态方法响应,我在调用 [self statemethod] 后正在执行一项任务。该任务需要 'state methodresponce. That task is executing before getting the data from state method. The method exits afterNSURLConnection` 行。我想异步运行该方法。请帮帮我。

【问题讨论】:

  • “编译器将方法留在中间”?什么意思?
  • 我从another method 打电话给stateMethod。编译器将编译到NSURLConnection 行,之后它将退出该方法并执行该行之后的一些任务,即[self stateMethod]; .再次编译器进入该方法并执行剩余的行(即NSURLConnection之后)。
  • 当你说“编译”时,你确定你不是指“运行”。您似乎也对异步操作的概念感到困惑,因为您所描述的听起来是对的;即在后台建立连接,并在收到响应时调用完成处理程序。
  • 你说得对。它只在应用程序运行时发生。我放调试器看应用的流程,那个时候方法会在中间退出。
  • 但这是正确的。连接将在后台线程中发生,stateMethod 将退出。

标签: ios objective-c asynchronous semaphore synchronous


【解决方案1】:

我正在从另一个方法调用一个方法。该方法在中间退出。完成一些任务后,它会运行剩下的方法。

它不会在中间退出...sendAsynchronousRequest 调用之后的部分是一个完成处理程序。这是一个单独的代码块,您将其传递到请求中以便稍后运行。将其视为方法的参数,而不是 stateMethod 代码的一部分。

考虑到这一点,您可以看到stateMethod 确实运行到了最后,因为方法中的最后一行代码是sendAsyncronousRequest 调用。

基于状态方法响应,我在调用 [self statemethod] 后正在执行一项任务。该任务需要state 方法响应。该任务在从状态方法获取数据之前执行。该方法在NSURLConnection 行之后退出。我想异步运行该方法。

由于您没有给出需要响应的方法的名称,我们就将其命名为foo。您的问题是请求是异步的,因此在响应可用之前调用 foo。处理该问题的一种方法是将调用 foo 放在请求的完成块中,但您可能不想直接这样做,因为可能会从多个位置调用 stateMethod,其中只有一个随后调用 foo .相反,您可以更改 stateMethod 以便调用者可以指定完成块:

-(void)stateMethodWithCompletion:(nullable void (^)(NSURLResponse* response))stateCompletion {
    [self.pickerView selectRow:0 inComponent:0 animated:YES];
    lblTitle.text=@"State";
    self.stateTF.text=@"";
    self.stateTF.inputView=_pickerView;
    [self.stateTF setInputAccessoryView:toolBar];
    NSString * method=@"***************************?countryID=";
    NSString *urlString=[NSString stringWithFormat:@"%@%@%@",MAIN_URL,method,_countryId];
    NSURL *url_ac=[[NSURL alloc]initWithString:urlString];
    NSMutableURLRequest *request_ac=[[NSMutableURLRequest alloc]initWithURL:url_ac];
    [request_ac setValue:loginUser.acessTokenStr forHTTPHeaderField:@"access_token"];

    [NSURLConnection sendAsynchronousRequest:request_ac queue:[NSOperationQueue currentQueue] completionHandler:
        ^(NSURLResponse ac_response, NSData acData, NSError *connectionError) {
        if (connectionError) {
             NSLog(@"ERROR CONNECTING DATA FROM SERVER: %@", connectionError.localizedDescription);
        }
        else {
            if (stateCompletion != nil) {
                stateCompletion(acResponse);
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                     NSString *responseString = [[NSString alloc] initWithData:acData encoding:NSUTF8StringEncoding];
                     [self parseStateListResult:acData];
                 });
        }
    }];  
}

这取代了旧的stateMethod,但如果您想要一个没有额外参数的版本,您也可以随时这样做:

-(void)stateMethod {
     [self stateMethodWithCompletion:nil];
}

【讨论】:

  • 我试过你的代码。它也像以前一样工作。
  • 我得到了我想要的输出。我在使用条件得到 URL 响应后将我的任务放在了state method。谢谢你的帮助。
  • 根据您要执行的操作,您可能需要或想要在主线程上运行 stateCompletion 块。如果是这样,请将if (stateCompletion != nil)... 块移动到被分派到主线程的块内。
猜你喜欢
  • 2021-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-04
  • 1970-01-01
  • 1970-01-01
  • 2019-03-28
  • 1970-01-01
相关资源
最近更新 更多