【问题标题】:Why does my UI update when I explicitiy leave out return to main thread为什么当我明确遗漏返回主线程时我的 UI 会更新
【发布时间】:2017-07-02 08:31:41
【问题描述】:

根据这个问题https://stackoverflow.com/a/23155684/1898829,必须在主线程上进行UI更新

[[session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response,
                                NSError *error) {
                if (data != nil) {
                    NSDictionary *responseDictionary =
                    [NSJSONSerialization JSONObjectWithData:data
                                                    options:kNilOptions
                                                      error:&error];
//                        dispatch_async(dispatch_get_main_queue(), ^{
                            CarListModel *carListModel = [[CarListModel alloc]
                                                          initWithArray:responseDictionary[@"placemarks"]];
                            completion(carListModel, error);
//                        });
                    } else {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            completion(nil, error);
                        });
                    }
                }] resume];

当注释掉 dispatch_async(dispatch_get_main_queue(), ^{ 我的应用程序仍然像以前一样工作。我的 tableview 得到更新,我的活动指示器停止。

这个完成块进入一个视图模型,它有一个完成块,它进入视图控制器。我不是说它必须回到主线程。

为什么我的 UI 没有被阻塞,或者它是否有可能在没有我明确设置的情况下返回到主线程

dispatch_async(dispatch_get_main_queue(), ^{

【问题讨论】:

  • 你没有“返回”到主线程。主线程并行运行。 -dataTaskWithRequest 可能使用在另一个线程上运行的队列。因此你不能阻塞主线程。只有主线程上的代码才能阻塞主线程。
  • 我的 UI 更改不是在主线程上完成的吗?如果它们是在主线程上完成的,为什么?
  • 如果你在主队列的分派之外运行完成处理程序,它会在主线程之外执行。由于我不知道完成处理程序的代码,我不能说,在什么队列上做了什么。

标签: ios objective-c multithreading


【解决方案1】:

你说得对,UI 更新必须在主线程上完成。您错误地认为不在主线程上执行此操作将导致不执行任何操作。要是这样就好了。如果您不在主线程上进行 UI 更新,则应用程序可能随时以奇怪和意想不到的方式失败。这意味着它可能会在几分钟后崩溃。动画可能会突然停止工作。视图可以随机消失或出现。导航栏可能不在位。换句话说,行为是未定义的。

所以你应该

1) 从后台线程更新 UI 时始终使用 dispatch_async(dispatch_get_main_queue(), ^{

2) 如果您有可能意外从后台线程调用的方法,请使用以下方法保护它们:

if (![NSThread mainThread]) {
    // log to crash reporter without crashing
    NSError* error = [NSError errorWithDomain:@"accessing UI outside of main thread" code:-1 userInfo:nil];
    [[Crashlytics sharedInstance] recordError:error withAdditionalUserInfo:@{@"file":__FILE__, @"line":@(__LINE__)}];
    return;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多