2

I have a view based NSTableView that uses the views of NSViewController subclasses (InspectorViewController) :

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    // Get inspector view controller
    InspectorViewController *inspectorViewController = [_inspectorViewControllers objectAtIndex:row];

    // Return its view
    return inspectorViewController.view;
}

All is ok except that the view of NSViewController is never released when I remove the view controller (which is well released).

If I use this code instead :

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    // Get inspector view controller
    InspectorViewController *inspectorViewController = [_inspectorViewControllers objectAtIndex:row];

    // Return its view
    NSTableCellView *view = [[NSTableCellView alloc] init] autorelease];
    [view addSubview:inspectorViewController.view];
    return view;
}

The view is correctly released when I remove the view controller. Here is the code for removing a view controller :

- (void)inspectorViewControllerClosed:(InspectorViewController *)inspectorViewController {
    // Get index of inspector view controller
    NSUInteger index = [_inspectorViewControllers indexOfObject:inspectorViewController];

    // Remove inspector view controller in array
    [_inspectorViewControllers removeObject:inspectorViewController];

    // Create index set
    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];

    // Begin updates
    [_tableView beginUpdates];

    // Move row in table view
    [_tableView removeRowsAtIndexes:indexSet withAnimation:NSTableViewAnimationEffectFade];

    // End updates
    [_tableView endUpdates];
}

I tried to reproduce the problem with a small sample code and I have the same problem, the view of view controller is only released when I don't return directly the view of view controller.

Anybody can help me please ?

Johnmph
  • 3,391
  • 24
  • 32

2 Answers2

1

Found, NSTableView retains view for reusing, it is correctly released with this code :

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    // Get inspector view controller
    InspectorViewController *inspectorViewController = [_inspectorViewControllers objectAtIndex:row];

    // Disable reusing ?
    [_inspectorViewController.view setIdentifier:nil];

    // Return its view
    return inspectorViewController.view;
}
Johnmph
  • 3,391
  • 24
  • 32
0

You could use:

[inspectorViewController.view removeFromSuperview]

before removing the view controller.

Rakesh
  • 3,370
  • 2
  • 23
  • 41
  • Why? Is this not automatically done by NSTableView removeRowsAtIndexes:withAnimation:? When I use the solution which works (Englobing the view of view controller in another view), all is ok without the need of calling removeFromSuperview – Johnmph Feb 23 '13 at 17:42
  • Thats probably because you are autoreleasing the parent view and the child view would get released in the process. I don't know if 'removeRowsAtIndexes:withAnimation' does that? Did you try it out? – Rakesh Feb 23 '13 at 17:44
  • tableView:viewForTableColumn:row: asks for an autoreleased view, it's why I autoreleased parent view in the second example. When I return inspectorViewController.view, I don't retain it so it must be released when view controller is released (because it retains it) and when the view is removed from table view (done by removeRowsAtIndexes:withAnimation or reloadData). – Johnmph Feb 23 '13 at 17:48
  • Alright. And how are you checking if the view is released or not? – Rakesh Feb 23 '13 at 17:53
  • Just a subclass of NSView with log on dealloc – Johnmph Feb 23 '13 at 17:57
  • Hmm. Maybe you could subclass the NSTableCellView just for checking if the dealloc is getting called for that view. Otherwise i'm out of ideas right now. :| – Rakesh Feb 23 '13 at 18:01
  • Already done and NSTableCellView is released. I checked the call stack for retain / release of view in the good and bad code and there is a [NSTableRowView setView:atColumn:] that retains view in the bad code which doesn't appear in the good code. Maybe it's the problem but it's internal to NSTableView – Johnmph Feb 23 '13 at 18:13
  • Found, NSTableView retains view for reusing, so I added [_inspectorViewController.view setIdentifier:nil]; and it is released. Thanks anyway for the help – Johnmph Feb 23 '13 at 18:27
  • Cool. Thanks for the info. I don't get it though, why a NSTableViewCell is not reused in the same situation. – Rakesh Feb 23 '13 at 19:00
  • Maybe because the view of a view controller has its identifier set by the view controller and a new NSView has no identifier ? – Johnmph Feb 23 '13 at 19:40