Ios 如何将异步方法转换为同步方法

Ios 如何将异步方法转换为同步方法,ios,objective-c,asynchronous,semaphore,synchronous,Ios,Objective C,Asynchronous,Semaphore,Synchronous,我正在从另一个方法调用一个方法。该方法在中间文件中存在。完成某些任务后,它将运行剩余的方法 -(void)stateMethod{ [self.pickerView selectRow:0 inComponent:0 animated:YES]; lblTitle.text=@"State"; self.stateTF.text=@""; self.stateTF.inputView=_pickerView; [self.stateTF setInputA

我正在从另一个方法调用一个方法。该方法在中间文件中存在。完成某些任务后,它将运行剩余的方法

-(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];
         });
     }
 }];  
}
调用state方法时需要响应。基于状态方法响应,我在调用[self-statemethod]后正在执行一个任务。该任务需要“状态方法<代码>响应”。该任务在从state方法获取数据之前执行。 该方法在NSURLConnection`行之后退出。我想异步运行该方法。请帮帮我

我正在从另一个方法调用一个方法。该方法在中间文件中存在。完成某些任务后,它将运行剩余的方法

-(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];
         });
     }
 }];  
}
它不在中间退出…
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];
}

“编译器将方法保留在中间位置”?你是什么意思?我正在从另一个方法调用
stateMethod
。编译器将编译到
NSURLConnection
行,然后退出该方法并执行该行后面的一些任务,即[self stateMethod]。再次输入此方法并执行剩余的行(即,在
NSURLConnection
之后)。当您说“compiling”时,您确定不是指“running”。您似乎也对异步操作的概念感到困惑,因为您所描述的听起来是正确的;i、 e.连接在后台建立,当收到响应时调用完成处理程序。您说的是正确的。它只发生在应用程序运行时。我让调试器查看应用程序的流程,此时方法将在中间退出。但这是正确的。连接将在后台线程中发生,并且
stateMethod
将退出。我尝试了你的代码。它也像以前一样工作。我已经得到了我想要的输出。在使用条件获得Url响应后,我将我的任务放置在
stateMethod
中。感谢你的帮助。取决于你尝试执行的操作,您可能需要或想要在主线程上运行
stateCompletion
块。如果是这样,将
If(stateCompletion!=nil).
块移动到调度到主线程的块中。