如何从http请求得到响应之前停止主ui线程

时间:2017-04-20 10:41:03

标签: ios objective-c

我的目标场景: 尝试向我的应用程序服务器发送一个简单的HTTP请求,并获得一个json响应。基于json响应,我需要执行segue操作。

我当前的情景: 这发生在我的系统中。经过太多延迟后,我得到了我的HTTP请求的json响应,因为我的响应是在延迟之后,执行segue甚至没有检查响应中的数据。

我的要求 如何让我的segue等到我收到HTTP请求的响应?

[application getjsonResponse];
     if([[defaults stringForKey:@"status"] isEqual:@"success"])
        {

            return YES;

        }

这些是我使用的代码行。我不希望我的线程在条件执行时执行此操作,除非我得到HTTP请求的响应。

到目前为止我尝试了

  1. 我尝试了线程睡眠方法,它有时会起作用,有时却没有。
  2. 在我得到回应之前,我有点迭代了一段时间。
  3. 好奇的问题
    当我从桌面浏览器(Chrome)或移动浏览器向我的应用程序提出相同的请求时,我立即得到响应但是当我使用代码时,我似乎在延迟10秒或更长时间后得到结果。这是为什么?

    这是我用来向我的应用服务器发送http请求的一段代码。

    -(void)getjsonResponse
    {
    NSURL *url=[NSURL URLWithString: URLForApplication];
    NSURLRequest *req=[NSURLRequest requestWithURL:url];
    NSURLSession *session = [NSURLSession sharedSession];
    
    NSURLSessionDataTask connection=[session dataTaskWithRequest:req completionHandler:^(NSData data, NSURLResponse response, NSError error)
     {
         if (!error){
                                         // Success
                if ([response isKindOfClass:[NSHTTPURLResponse class]])
                {
                    NSError *jsonError;
                    NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
                    if (jsonError)
                    {                       // Error Parsing JSON
                    }
                    else
                    {   // Success Parsing JSON
                        // Log NSDictionary response:                                                      
                        NSLog(@"%@",jsonResponse);
                        {                     
                            NSString * statusCode=[[NSString alloc]init];
                            statusCode=jsonResponse[@"statusCode"];
                            _statusOtpResponse=jsonResponse[@"status"];
                            NSLog(@"status value: %@",_statusOtpResponse);
                            NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
                            [defaults setObject:_statusOtpResponse forKey:@"status"];
                            [defaults setObject:statusCode forKey:@"statuscodeOtp"];
                            [defaults synchronize];                                           
                        }
                    }
                }
                else
                {
                                                      //Web server is returning an error
                }
            }
            else
            {
                                                  // Fail
                                                  NSLog(@"error : %@", error.description);
            }
    
        }];
            if(connection){
                [connection resume];
            }
    

2 个答案:

答案 0 :(得分:1)

确定。你的问题有很多不一致之处。例如,您谈到执行segue但您的代码不包含任何操作。

无论如何,首先我会说停止/暂停你的应用程序的主线程是一个坏主意。期。当你做这样的事情,或以任何方式在主线程上运行需要花费大量时间执行的代码时,你有效地使应用程序无响应,并且用户将无响应的应用程序视为质量差,因此不是值得使用。

以下是我将如何重写您的代码以执行segue。注意主线程上的回调。

NSURL *url = [NSURL URLWithString: URLForApplication];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];

// Do something here to indicate a server query is executing.
// For example, displaying a UIActivityIndicatorView

// Note: you had a missing '*' on this line
NSURLSessionDataTask *connection = [session dataTaskWithRequest:req completionHandler:^(NSData data, NSURLResponse response, NSError error) {

    // First error check. 
    if (error) {
        // Log and/or display alert with error message and finish.
        // Reset display to non busy mode on main thread.
        NSLog(@"error : %@", error.description);
        return;
    }

    // We're here, so request was a success
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {

        NSError *jsonError;
        NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
        if (jsonError) {
            // Log and/or display alert with error message and finish.
            // Reset display to non busy mode on main thread.
            NSLog(@"error : %@", error.description);
            return;
        }

        // We're here, so JSON parse was a success
        NSLog(@"%@", jsonResponse);
        NSString *statusCode = jsonResponse[@"statusCode"];
        NSString *statusOtpResponse = jsonResponse[@"status"];
        if (/* test variables to decide if to execute the segue */) {

            // Now we know we want to execute the segue.
            dispatch_async(dispatch_get_main_queue(), ^{
                [self performSegueWithIdentifier:@"segue-id" sender:self];
            });
        }

        // Removed your code for storing response codes in user defaults because I simply could not see why you would do that.
    }];

    // Execute
    [connection resume];

```

答案 1 :(得分:0)

NSURLSessionDataTask已由系统异步执行。

因此,如果您想在从请求中接收数据后执行segue,只需将您的segue代码放在完成块中。

在您的情况下,在处理响应数据之后,例如在行:

之后
[defaults synchronize];  

请注意,在再次对主线程进行操作之前,应首先调度到主线程。

dispatch_async(dispatch_get_main_queue(), ^{
   // YOUR SEGUE HERE
});