NSInternalInconsistencyException, доступ к _cachedSystemAnimationFence требует основного потока

Используя Crittercism с некоторыми бета-тестерами, я вижу ошибку, появившуюся несколько раз, что я никогда не испытывал сам, и я не могу реплицироваться.

Критерий говорит мне: NSInternalInconsistencyException, доступ к _cachedSystemAnimationFence требует основного потока

И строка, на которую он указывает, - это:

[picker dismissViewControllerAnimated:YES completion:^{

Выполняя некоторое чтение в StackOverflow, кажется, что любой код пользовательского интерфейса должен запускаться в основном потоке. Является ли ошибка, с которой я сталкиваюсь, потому что функция rejectViewControllerAnimated запущена в фоновом потоке?

Любопытно, почему эта ошибка относительно случайна (т.е. я не могу ее воспроизвести), а также как ее исправить.

- (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];

            }];

        }];
    }];

}

Ответ 1

Если нам нужно вызвать любую связанную с UI операцию внутри отправки блочного использования. Все, что взаимодействует с пользовательским интерфейсом, должно выполняться в основном потоке. Вы можете запускать другие задачи, которые не связаны с пользовательским интерфейсом за пределами основного потока, для повышения производительности.

dispatch_async(dispatch_get_main_queue(), ^{
    // Call UI related operations
});

Ответ 2

Я боюсь, что у меня нет решения, но я могу предложить детали приложения, которое рушится таким же образом. Мы используем платформу Cordova для создания нашего приложения. Этот сбой, похоже, происходит только в iOS9 (на нашем iPhone 6 в нашем случае), и только тогда, когда у пользователя установлена ​​клавиатура Swype. Мы видим крах при открытии/закрытии клавиатуры для ввода текстового поля, отображаемого через плагин Cordova InAppBrowser, и только иногда. При удалении приложения Swype ошибка исчезнет. К сожалению, поскольку мы не писали ни одного из objc, участвующих в приложении, у нас сложная отладка времени. Удачи!

Ответ 3

Убедитесь, что ваше завершениеHandler на самом деле получает обратный вызов в основном потоке, а не какой-либо другой поток. Это обычно является причиной этой конкретной проблемы.

Ответ 4

Для Swift 3

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

Для меня это решение исправлено при попытке открыть pdfViewer в ландшафтном режиме.