0

我以这种方式实现了登录方法:

      [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 服务的下一部分。这根本不是用户友好的!欢迎任何想法:)

4

1 回答 1

1

根据文档,您必须以任何方式从主线程调用更新用户界面的方法UIKit

在大多数情况下,只在应用程序的主线程中使用 UIKit 类。对于从 UIResponder 派生的类或涉及以任何方式操作应用程序的用户界面的类尤其如此。

我建议您尝试限制对主线程进行的回调次数,因此您希望尽可能多地批量处理用户界面更新。

然后,正如您正确地说的那样,您所要做的就是dispatch_async在您需要从后台处理中更新 UI 时使用回调到您的主线程。

因为它是异步的,它不会中断你的后台处理,并且应该对主线程本身有最小的中断,因为更新大多数UIKit组件的值相当便宜,它们只会更新它们的值并触发它们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];
        }
    });
});
于 2016-02-06T22:59:51.523 回答