Предупреждение CoreAnimation при обновлении NSProgressIndicator через блок, выполненный в главной очереди

У меня есть следующий сценарий для экспорта сущностей базовых данных в JSON и отображения индикатора выполнения при этом.

Иногда, после того, как лист с индикатором выполнения отклоняется после завершения экспорта, я получаю следующее предупреждение в виде сообщения консоли:

CoreAnimation: предупреждение, удаленный поток с незафиксированной CATransaction; установите CA_DEBUG_TRANSACTIONS=1 в среде, чтобы регистрировать трассировки.

AppDelegate.m

//  AppDelegate.m

- (void)exportAsJSON:(id)sender;
{
    NSSavePanel *savePanel = [NSSavePanel savePanel];

    [savePanel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) {
        WMJSONExportOperation *operation = nil;

        if (result == NSFileHandlingPanelOKButton)
        {
            [_progressIndicator setDoubleValue:0];
            operation = [[WMJSONExportOperation alloc] init];

            // setProgressCallbackBlock
            [operation setProgressCallbackBlock: ^(double progress) {
                [[NSOperationQueue mainQueue] addOperationWithBlock:^
                 {
                     [_progressIndicator setDoubleValue: progress];
                 }];
            }];

            // setExportCompletionBlock
            [operation setExportCompletionBlock:^(NSData *data, NSError *error) {
                // Insert code here to save data to disk
                [_window endSheet:_exportProgressSheet];
            }];

            [_window beginSheet:_exportProgressSheet completionHandler:^(NSInteger result) {
                NSLog(@"ExportProgressSheet completionHandler executed");
            }];

            NSOperationQueue *queue;
            queue = [[NSOperationQueue alloc] init];
            [queue addOperation:operation];
        }

    }];
}

WMJSONExportOperation.m, подкласс NSOperation:

- (void)main;
{
    NSError *error = nil;
    NSData *data = nil;

    // just for illustrating the problem:
    for (int i=1; i<=10; i++) {
        sleep(1);
        [self progressCallbackBlock](i * 10);
    }

    [self exportCompletionBlock](data, error);
}

@end

Итак, первый вопрос: это всего лишь предупреждение, мне все равно?

Второй вопрос, как избежать предупреждения. Есть вопросы о SO, описывающие подобные проблемы, но предлагаемое решение часто состоит в том, чтобы манипулировать NSProgressIndicator только из основной очереди. Разве это не то, что я делаю с этим кодом:

    // setProgressCallbackBlock
    [operation setProgressCallbackBlock: ^(double progress) {
        [[NSOperationQueue mainQueue] addOperationWithBlock:^
         {
             [_progressIndicator setDoubleValue: progress];
         }];
    }];

1 ответ

Решение

После дальнейшего изучения сообщения, установив переменную среды CA_DEBUG_TRANSACTIONS, я обнаружил, что проблема не в том, что сообщение отправлено NSProgressIndicator, но закрытие листа, которое я действительно инициировал из другой очереди, чем основная очередь.

Так что это изменение исправляет мою проблему:

[_window endSheet:_exportProgressSheet];

будет выглядеть так:

[[NSOperationQueue mainQueue] addOperationWithBlock:^
   {
      [_window endSheet:_exportProgressSheet];
   }];
Другие вопросы по тегам