我以这种方式实现了登录方法:
[KVNProgress show];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//some error handling like:
if ([_usernameField.text length] < 4) {
[KVNProgress showErrorWithStatus:@"Username too short!"];
_passwordField.text = @"";
return;
}
//Then I call login web service synchronously here:
result = [ServerRequests login];
dispatch_async(dispatch_get_main_queue(), ^{
if(!result)
{
[KVNProgress showErrorWithStatus:@"problem!" completion:NULL];
_passwordField.text = @"";
}
else if([result.successful boolValue])
{
[KVNProgress showSuccessWithStatus:result.message];
}
});
});
它主要崩溃,并且只有主要队列(没有优先级默认值)的周围区块崩溃了!但问题是:KVNProgress只在错误处理区域显示而不是我们称之为Web服务的下一部分。它根本不是用户友好的!欢迎任何想法:)
答案 0 :(得分:1)
根据the UIKit
documentation 必须从主线程中调用以任何方式更新用户界面的方法:
在大多数情况下,仅使用应用程序主线程中的UIKit类 。对于从UIResponder 派生的类或涉及以任何方式操纵应用程序的用户界面的类,尤其如此。
我建议您尝试限制对主线程进行回调的次数,因此您希望尽可能多地批量处理用户界面更新。
然后,正如您所说的那样,只要您需要在后台处理中更新UI,就可以使用dispatch_async
回调主线程。
因为它是异步的,它不会中断你的后台处理,并且应该对主线程本身造成最小的中断,因为大多数UIKit
组件的更新值相当便宜,它们&# 39;只需更新它们的值并触发它们setNeedsDisplay
,以便它们在下一个运行循环中重新绘制。
从您的代码中,您的问题似乎是您从后台线程调用此问题:
if ([_usernameField.text length] < 4) {
[KVNProgress showErrorWithStatus:@"Username too short!"];
_passwordField.text = @"";
return;
}
这是100%的UI更新代码,因此应该在主线程上进行。
虽然,我不知道KVNProgress
的线程安全性,但我认为它也应该在主线程上调用,因为它向用户提出错误。
因此,您的代码应该像这样 (假设它首先在主线程上发生):
[KVNProgress show];
//some error handling like:
if ([_usernameField.text length] < 4) {
[KVNProgress showErrorWithStatus:@"Username too short!"];
_passwordField.text = @"";
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Then I call login web service synchronously here:
result = [ServerRequests login];
dispatch_async(dispatch_get_main_queue(), ^{
if(!result) {
[KVNProgress showErrorWithStatus:@"problem!" completion:NULL];
_passwordField.text = @"";
} else if([result.successful boolValue]) {
[KVNProgress showSuccessWithStatus:result.message];
}
});
});