Предупреждение 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];
}];