2013-12-15 5 views
1

У меня есть приложение, которое выполняет асинхронную запись на сервер. Затем он декодирует json и возвращает сообщение с сервера. Я помещаю несколько записей журнала отладки в свой код, поэтому я знаю, что ответ с сервера, а также декодирование json мгновенно. Проблема заключается в том, что после того, как json будет декодирован, задача async запускается около 6 секунд, прежде чем она вызовет следующее событие (показ всплывающего диалогового окна).iOS async task freezes

- (IBAction)register:(id)sender { 
    [self startPost]; // Starts spinner animation 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     [self doPost]; // performs post 
    }); 
} 


-(void)doPost 
{ 

@try { 



      NSString *post =[[NSString alloc] initWithFormat:@"request=register&platform=ios&email=%@&password=%@",self.email.text,self.password.text]; 
      //NSLog(@"PostData: %@",post); 

      NSURL *url=[NSURL URLWithString:@"https://site.com/api.php"]; 

      NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; 

      NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]]; 

      NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 
      [request setURL:url]; 
      [request setHTTPMethod:@"POST"]; 
      [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; 
      [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
      [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 
      [request setHTTPBody:postData]; 

      //[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]]; 

      NSError *error = [[NSError alloc] init]; 
      NSHTTPURLResponse *response = nil; 
      NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

      //NSLog(@"Response code: %d", [response statusCode]); 
      if ([response statusCode] >=200 && [response statusCode] <300) 
      { 
       NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding]; 
       //NSLog(@"Response ==> %@", responseData); 
       NSData *responseDataNew = [responseData dataUsingEncoding:NSUTF8StringEncoding]; 
       NSError* error = nil; 
       NSDictionary *myDictionary = [NSJSONSerialization JSONObjectWithData:responseDataNew options:NSJSONReadingMutableContainers error:&error]; 





       if (error){ 
        [self alertStatus:@"Unknown response code from server" :@"Whoops!"]; 
        NSLog(@"Response ==> %@", responseData); 
        [self postDone]; 
       }else{ 
        if ([myDictionary[@"error"] isEqualToNumber:(@1)]) 
        { 
         NSLog(@"ERROR DETECTED"); 
         [self alertStatus:myDictionary[@"message"]:@"Whoops!"]; 
         [self postDone]; 
        } 
        else 
        { 
         [self alertSuccess]; 
         [self postDone]; 
        } 
       } 
      } else { 
       if (error) NSLog(@"Error: %@", error); 
       [self alertStatus:@"Connection Failed" :@"Whoops!"]; 
       [self postDone]; 
      } 


    } 
    @catch (NSException * e) { 
     NSLog(@"Exception: %@", e); 
     [self alertStatus:@"Registration Failed." :@"Whoops!"]; 
     [self postDone]; 
    } 
} 

-(void)startPost 
{ 
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 

self.email.enabled = false; 
self.password.enabled = false; 
self.confirm.enabled = false; 
self.cancelButton.enabled = false; 
} 

- (void) alertStatus:(NSString *)msg :(NSString *)title 
{ 
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title 
                message:msg 
                delegate:self 
              cancelButtonTitle:@"Ok" 
              otherButtonTitles:nil, nil]; 
[alertView setTag:0]; 
[alertView show]; 
} 
- (void) alertSuccess 
{ 
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Success!" 
                message:@"You have been successfully registered." 
                delegate:self 
              cancelButtonTitle:@"Ok" 
              otherButtonTitles:nil, nil]; 
[alertView setTag:1]; 
[alertView show]; 
} 
-(void)postDone 
{ 

self.registerButton.hidden = false; 
self.spinner.hidden = true; 
self.loadingText.hidden = true; 
//[UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 

self.email.enabled = true; 
self.password.enabled = true; 
self.confirm.enabled = true; 
self.cancelButton.enabled = true; 

} 
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 
{if (alertView.tag == 1) 
{ 
[self dismissViewControllerAnimated:YES completion:nil]; 
}} 

Функции alertStatus и alertSuccess просто отображают окно сообщения ненадолго. Когда я запускаю код, я целенаправленно вводил плохую информацию, поэтому в журнале говорится: «ОШИБКА ОБНАРУЖЕНА». Проблема в том, что требуется еще 6 секунд, прежде чем что-нибудь случится после этого.

+0

Вы не показываете метод postDone. Я предполагаю, что вы показываете представление предупреждения. Это нужно сделать на основной теме. – rmaddy

+0

@rmaddy Я отредактировал исходное сообщение и добавил его в метод 'postDone'. – DarthCaniac

+0

Вам нужно вызвать два метода «alert ...» в основном потоке. Это бесчисленное множество примеров. Найдите 'dispatch_async' и' dispatch_get_main_queue'. – rmaddy

ответ

2

После называется:

NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

и получены данные, вы должны переключиться обратно в основной поток, чтобы использовать его. Это связано с тем, что все обновления пользовательского интерфейса должны выполняться в основном потоке.

Таким образом, все, что код после того, как вы получите эти данные должны быть перемещены на новый метод и называется:

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self handleData:urlData withResponse:response error:error]; 
} 

И вы должны также положить код исключения поймать внутри dispatch_async(dispatch_get_main_queue(), ^{, потому что вы пытаетесь обновить пользовательский интерфейс там тоже ...

+0

Спасибо большое, он отлично работает сейчас :) – DarthCaniac