objective-cnstableviewnsviewnsprintoperation

NSTableView data disappears when print panel settings are changed


I am trying to print data populated in an NSTableView through a custom NSView. When the print command is issued by the user, the custom NSView containing the NSTableView is shown in the Print Panel as expected

The problem I am encountering is as follows: if the user changes any settings in the Print Panel, the data populating the NSTableView is blanked out. The same thing happens if the user clicks Print. My question: how do I make the data not disappear when the user interacts with the Print Panel?

Additional Information: (1) There are labels in the NSView that appear as expected, and (2) If I bypass the Print Panel, by issuing [printOp setShowsPrintPanel:NO]; [printOp runOperation]; the data in the NSTableView prints as expected.

Speculation: I am in the process of updating my program to use Automatic Reference Counting (ARC). It almost seems as if the pointer to the data is being released early, such that when the user interacts with the Print Panel the data is not longer available to the NSView; but I am not able to determine where that happens (my code is not being accessed, as far as I can tell, after the Print Panel is first presented).

Any help would be greatly appreciated. Thank you. Attached is some of the code to help in diagnosis.

From MyDocument.m (subclass of NSDocument), the code that kicks off the print operation:

-(NSPrintOperation *)printOperationWithSettings:(NSDictionary *)ps error:(NSError **)e
{
    DeductionTablePrintViewController *pvc = [[DeductionTablePrintViewController alloc] initWithScopeDeduction:deduction andHelper:helper andDeductionController:self];

    NSPrintInfo *printInfo = [self printInfo];

    NSRect viewFrame = [[pvc view] frame];
    viewFrame.size.width = [printInfo imageablePageBounds].size.width;
    [[pvc view] setFrame:viewFrame];

    NSPrintOperation *printOp = [NSPrintOperation printOperationWithView:[pvc view] printInfo:printInfo];
    return printOp;
}

DeductionTablePrintViewController is a subclass of NSViewController used strictly for printing. There is a corresponding xib file. From DeductionTablePrintViewController.h (hooked up to the xib:

IBOutlet DeductionTable *deductionTable;

Now for DeductionTablePrintViewController.m:

-(id)initWithScopeDeduction:(ScopeDeduction *)aDeduction andHelper:(DeductionHelper *)aHelper andDeductionController:(MyDocument *)aDeductionController
{
    self = [super initWithNibName:@"DeductionTablePrintView" bundle:nil];
    if (self) {
        // Set deduction
        deduction = [aDeduction copy]; // Deep copy
        deductionController = aDeductionController; // MyDocument

        [[(DeductionTablePrintView *)[self view] deductionTable] setDeduction:deduction];
    }
return self;
}

-(id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)row
{
    id objectValue = nil;

    // objectValue is calculated here
    ... ... ...
return objectValue;
}

Solution

  • The view controller was being deallocated by ARC, as suggested by Willeke above (thank you). The solution was to add to MyDocument.h:

    DeductionTablePrintViewController *pvc;
    

    And then changing the method printOperationWithSettings to read:

    -(NSPrintOperation *)printOperationWithSettings:(NSDictionary *)ps error:(NSError **)e
    {
        pvc = [[DeductionTablePrintViewController alloc] initWithScopeDeduction:deduction andHelper:helper andDeductionController:self];
        .... ....
    }
    

    Once the referent was no longer being deallocated, the Print Panel worked as expected.

    Additional Information: An interesting aspect of this problem is that the view controller was deallocated after the Print Panel appeared, so the panel had time to create a print preview, but then did not have access to the data for the table. Also, I think the reason the formula, deduction identifier, and tableview (see pictures above) still appear after the view controller was deallocated was that the once they were drawn onto the view the Print Dialog did not try to redraw them. But the Print Panel repeatedly reads in data for the table with calls to tableView:objectValueForTableColumn:row. Further frustrating attempts to diagnose this problem were two things: (i) when the Print Panel calls tableView:objectValueForTableColumn:row on a deallocated view controller, no warning or error is issued, but instead fails silently; (ii) when I inserted a breakpoint in tableView:objectValueForTableColumn:row the debugger breaks before the Print Panel is shown to the user but not once the view controller is deallocated. This latter behaviour makes sense, since it is deallocated and the code cannot be run; but this led me to believe the Print Panel only sent messages to tableView:objectValueForTableColumn:row in the initial setup.