我有一个应用程序,它向服务器发送异步帖子。然后它解码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秒钟。
答案 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 ......