如何停止主 ui 线程,直到我得到来自 http 请求的响应
Posted
技术标签:
【中文标题】如何停止主 ui 线程,直到我得到来自 http 请求的响应【英文标题】:How to stop main ui thread until i get response from http request 【发布时间】:2017-04-20 10:41:02 【问题描述】:我的目标场景: 尝试向我的应用程序服务器发送一个简单的 HTTP 请求并获得一个 json 响应作为回报。根据 json 响应,我需要执行 segue 操作。
我目前的情景: 这发生在我的系统中。经过太多延迟后,我的 HTTP 请求得到了 json 响应,因为我的响应是在延迟之后执行的,甚至没有检查响应中的数据就执行了 segue。
我的要求 如何让我的 segue 等到我收到 HTTP 请求的响应?
[application getjsonResponse];
if([[defaults stringForKey:@"status"] isEqual:@"success"])
return YES;
这些是我使用的代码行。我不希望我的线程执行这个 if 条件,除非我得到对我的 HTTP 请求的响应。
到目前为止我尝试过的:
-
我尝试了线程睡眠方法,它有时有效,有时无效。
在我得到响应之前,我会迭代一个 while 循环。
好奇的问题 当我从桌面浏览器 (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];
【问题讨论】:
所以请使用正确的语法。此外,停止 UI 线程通常是一个非常糟糕的主意 - 它会使 GUI 响应并让用户认为应用程序可能崩溃了。 @tambre 所以我不想停止 ui 线程如何让 ui 线程等到我从 http 请求中得到响应请帮忙.. 【参考方案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];
```
【讨论】:
感谢回复..我使用 userdefaults 存储来自 jsonresponse 的值,我尝试从视图控制器中 userdefault 的 jsonresponses 中获取值,然后执行 segue。【参考方案2】:NSURLSessionDataTask 已经被系统异步执行了。
因此,如果您想在收到请求的数据后执行转场,只需将转场代码放在完成块中即可。
在您的情况下,就在您处理响应数据之后,例如在以下行之后:
[defaults synchronize];
请注意,在再次在主线程上工作之前,您应该先分派到主线程。
dispatch_async(dispatch_get_main_queue(), ^
// YOUR SEGUE HERE
);
【讨论】:
以上是关于如何停止主 ui 线程,直到我得到来自 http 请求的响应的主要内容,如果未能解决你的问题,请参考以下文章
在主线程上处理大型全局对象时如何不阻止来自工作线程的主 UI 线程
从 ui-thread 显示窗口有时会阻塞主 ui-thread