NSViewController view's not released when used in a view based NSTableView - macos

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 ?

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;
}

You could use:
[inspectorViewController.view removeFromSuperview]
before removing the view controller.

Related

IOS/Xcode/Storyboard: How can I segue from table row to modal view controller

This is a storyboard question, I think.
How do you create a segue from a table row to a new view controller?
Here is a picture of what it is supposed to look like.
I tried control dragging from the table to the view controller on the bottom but it does not take. If I embed the view controller in a navigator I can create a push segue but it does not work when you click on it.
This is the code I am using for that but first I would like to be able to replicate the storyboard in the picture. In any case I want the new view controller to pop up when you click on the table row.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Store Selection
[self setSelection:indexPath];
}
...
else if ([segue.identifier isEqualToString:#"updateToDoViewController"]) {
NSLog(#"segue to update");
// Obtain Reference to View Controller
UpdateTodoVC *vc = (UpdateTodoVC *)[segue destinationViewController];
// Configure View Controller
[vc setManagedObjectContext:self.managedObjectContext];
if (self.selection) {
// Fetch Record
NSManagedObject *record = [self.fetchedResultsController objectAtIndexPath:self.selection];
if (record) {
[vc setRecord:record];
}
// Reset Selection
[self setSelection:nil];
}
}
}
Thanks for any suggestions.
You can't ctrl+drag from a "Prototype" cell! You can only do that with static cells. So you have to ctrl+drag from the UITableViewController to the next view controller, give it an identifier of updateToDoViewController, and perform the segue programatically:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Store Selection
[self setSelection:indexPath];
// Perform the segue with identifier: updateToDoViewController
[self performSegueWithIdentifier:#"updateToDoViewController" sender:self];
}

Customise table view cell in Mac app

Am trying to customise a table view cell. I have created a separate nib file for the cell. Have added a Table view Cell in it with the customised layout ( 2 textfields and an image). All of them have an outlet.
In,
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
MyCell *myCell = [tableView makeViewWithIdentifier:#"cellId" owner:self];
myCell.text1.stringValue = #"Foo";
myCell.text2.stringValue = #"Bar";
return myCell;
}
I know this is wrong implementation, but how can I load a new nib for a cell in a tableView ?
Are you using
- (void)registerNib:(NSNib *)nib forIdentifier:(NSString *)identifier
to register your cell xibs?

How does the NSTableView set content Mode(view-based or cell-based) by code?

As title.
How does the NSTableView set content Mode(view-based or cell-based) by code?
Thanks for helping
NSTableView defaults to being cell-based, which makes sense for backwards compatibility. Table views are view-based when the table view delegate implements -tableView:viewForTableColumn:row:. You can easily test by programmatically creating a table view as follows:
#implementation BAVAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSView *contentView = self.window.contentView;
NSTableView *tableView = [[NSTableView alloc] initWithFrame:(NSRect){{50, NSMaxY(contentView.frame) - 200}, {400, 200}}];
tableView.dataSource = self;
tableView.delegate = self;
[contentView addSubview:tableView];
NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:#"column"];
column.width = 400;
[tableView addTableColumn:column];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return 3;
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return [NSString stringWithFormat:#"%ld", row];
}
//- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
// NSTextField *textField = [[NSTextField alloc] initWithFrame:(NSRect){.size = {100, 15}}];
// textField.stringValue = [NSString stringWithFormat:#"%ld", row];
// return textField;
//}
#end
If you run this code with that delegate method commented out, you get a cell-based table view:
And if you uncomment that delegate method, you get a view-based table view:
The documentation for -tableView:viewForTableColumn:row: states that
This method is required if you wish to use NSView objects instead of NSCell objects for the cells within a table view. Cells and views can not be mixed within the same table view.
which hints at it being the condition that determines whether a table view is cell- or view-based.

Adding elements with content not working in NStable view in cocoa

I created a tableview and added image & text table view cell designed it now i thought to add another label in the row and assigned some values to the label based on the rows but it is not working and one more problem i cant hide label when the label in cell while in view i can able to hide
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSImage *profile=[NSImage imageNamed:#"header_menubg.png"];
NSString *identifer=[tableColumn identifier];
if([identifer isEqualToString:#"Mainidentifier"])
{
cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
[cellView.textField setStringValue:[_homearray objectAtIndex:row]];
[cellView.imageView setImage:profile];
return cellView;
}
if(row==0)
{
_countLabel.stringValue=#"40";
[cellView.textField setHidden:YES];
}
return nil;
}
And even i tried to hide text field in some rows that too not working what may be the problem

Using a different view in editing mode in a view based NSTableView

I have a NSTableView with a single NSTableCellView column that let's say, has an icon, name and an optional date.
When you edit a row, I want to replace the whole view with a simple NSTextField, and I will do some parsing to that text and extract that optional date, if present.
My question is, how would you implement this editing mechanism?
I tried returning a different view in the tableView:viewForTableColumn:row, something like:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
BOOL isSelected = [tableView isRowSelected:row];
if (isSelected)
{
NSView *view = [tableView makeViewWithIdentifier:#"editor" owner:self];
....snip....
return view;
}
else
{
TaskView *view = [tableView makeViewWithIdentifier:#"view" owner:self];
....snip....
return view;
}
}
and then whenever the selected row changes, trying to request a refresh on that row.
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
{
NSTableView *table = [aNotification object];
NSUInteger rowIndex = [table selectedRow];
[table reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:rowIndex]
columnIndexes:[NSIndexSet indexSetWithIndex:0]];
}
It doesn't quite work, and the code feels a bit dirty.
It must be a better way of doing this, and I can't seem to find in the docs or online.

Resources