访问_cachedSystemAnimationFence发生NSInternalInconsistencyException错误,需要在主线程中进行。

13

使用Crittercism与一些测试人员时,我发现出现了一个错误,这个错误出现了多次,但我自己从未遇到过,也无法复制。

Crittercism告诉我:NSInternalInconsistencyException访问_cachedSystemAnimationFence需要在主线程中进行。

它所指向的行是:

[picker dismissViewControllerAnimated:YES completion:^{

在StackOverflow上阅读了一些内容,似乎任何UI代码都应该在主线程上运行。我遇到的错误是否是因为dismissViewControllerAnimated在后台线程上运行?

我很好奇为什么这个错误相对随机(即我无法复现它),还有如何修复它。

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    __block PHObjectPlaceholder *assetPlaceholder;

    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{

        PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[info objectForKey:@"UIImagePickerControllerOriginalImage"]];

        assetPlaceholder = changeRequest.placeholderForCreatedAsset;

    } completionHandler:^(BOOL success, NSError *error) {

        NSArray *photos = [[NSArray alloc] initWithObjects:assetPlaceholder.localIdentifier, nil];
        PHFetchResult *savedPhotos = [PHAsset fetchAssetsWithLocalIdentifiers:photos options:nil];

        [savedPhotos enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) {

            NSMutableArray *images = self.event.eventAttachments;
            if (images) {
                [images addObject:asset];
            } else {
                images = [[NSMutableArray alloc]init];
                [images addObject:asset];
            }

            self.event.eventAttachments = images;

            [picker dismissViewControllerAnimated:YES completion:^{

                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:4];
                NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];

                [self.tblChildrenNotes beginUpdates];
                [self.tblChildrenNotes reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
                [self.tblChildrenNotes endUpdates];

            }];

        }];
    }];

}
4个回答

28
如果我们需要在代码块中调用与UI相关的操作,请使用dispatch。所有与UI交互的内容都必须在主线程上运行。您可以在主线程之外运行不涉及UI的其他任务,以提高性能。
dispatch_async(dispatch_get_main_queue(), ^{
    // Call UI related operations
});

这是尝试解决问题的非常明智的第一步。众所周知,UI更新应始终在主线程上执行。 - Nicolas Miari

4

很抱歉,我没有解决方案,但我可以提供一个应用程序的详细信息,它以同样的方式崩溃。我们使用Cordova平台构建我们的应用程序。这个崩溃似乎只发生在iOS9上(在我们的情况下是iPhone 6),而且只有当用户安装了Swype键盘时才会发生。当通过Cordova的InAppBrowser插件显示文本字段并打开/关闭键盘进行输入时,我们会看到崩溃,但有时候不会。删除Swype应用程序会使错误消失。不幸的是,由于我们没有编写任何涉及应用程序的objc,因此我们很难进行调试。祝你好运!


你解决了这个问题吗?或者你能提供任何解决方案吗? - km1882
你必须有一段代码,试图在后台线程上操作UI。将任何UI操作都包装在用户“iOS”上面发布的代码片段中。 - jungledev
我在 10.3.311.1.111.4 上发现了这个崩溃。 - wzso

4

对于Swift 3

    DispatchQueue.main.async(execute: {
       //UI Related Function
    });

对我来说,当尝试在横向模式下打开pdfViewer时,这个解决方案很有效。


1

检查确保您的completionHandler实际上是在主线程上被回调而不是其他线程。这通常是此特定问题的原因。


好主意,我会看一下。 - nwkeeley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接