iOS异步任务冻结

时间:2013-12-15 21:15:07

标签: ios json asynchronous

我有一个应用程序,它向服务器发送异步帖子。然后它解码json并从服务器返回消息。我在我的代码中添加了一些调试日志条目,所以我知道服务器的响应以及json的解码都是即时的。问题是,在解码json之后,异步任务在调用下一个事件之前运行大约6秒(显示弹出对话框)。

- (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函数只是简单地弹出一个消息框。 当我运行代码时,我故意输入错误信息,因此日志显示“ERROR DETECTED”。问题是在此之后发生任何事情需要6秒钟。

1 个答案:

答案 0 :(得分:2)

打完电话后:

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

并获取数据,您应该切换回主线程来使用它。这是因为所有UI更新都必须在主线程上完成。

因此,获取数据后的所有代码都应移至新方法并调用为:

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

你还应该将异常捕获代码放在dispatch_async(dispatch_get_main_queue(), ^{中,因为你也试图在那里更新UI ......