I have the following scenario for exporting Core Data entities to JSON and displaying a progress bar while doing so.
Sometimes, after the sheet with the progress bar is dismissed when the export is completed, i get the follwing warning as a console message:
CoreAnimation: warning, deleted thread with uncommitted CATransaction; set CA_DEBUG_TRANSACTIONS=1 in environment to log backtraces.
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, a subclass of 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 the first question is: It is just a warning, should I care?
The second question is, how to avoid the warning. There are questions on SO describing similar problems, but the suggested solution is often to manipulate the NSProgressIndicator only from the main queue. Isn't that exactly what I am doing with this code:
// setProgressCallbackBlock
[operation setProgressCallbackBlock: ^(double progress) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
[_progressIndicator setDoubleValue: progress];
}];
}];
After investigating the message further by setting the CA_DEBUG_TRANSACTIONS environment variable, I found, that the problem was not the message send to NSProgressIndicator
, but the closing of the sheet, that I did indeed trigger from another queue than the main queue.
So this change fixes my problem:
[_window endSheet:_exportProgressSheet];
becomes:
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
[_window endSheet:_exportProgressSheet];
}];