Custom NSView for NSTableView not updating components - objective-c

I created a custom NSView for a NSTableView.
I am trying to fill the fields I created in it using the Interface Builder but I can't. I would say each component is properly linked and the code is OK.
This is the function
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
Account *account = (Account *)[self.dataSource objectAtIndex:row];
AccountTableCellViewController *controller = [[AccountTableCellViewController alloc] init];
controller.subtitleLabel.stringValue = account.name;
[controller.titleLabel setStringValue:account.num];
NSLog(#"%#", controller.titleLabel);
return [controller view];
}
And here is the picture of the bindings:
The table shows all the rows correctly, but is not filling the NSTextFields as expected.
UPDATE:
This is how it looks like (not updating views):
Any suggestion?

The labels haven't been loaded from the nib yet. I'd just create an extra account instance variable in your view controller, assign it there, then load the information in -(void)awakeFromNib

Related

Custom NSView inside a column of a NSTableView

I am using a view-based NSTableView with only one column.
I have the following code, which returns an NSView with two NSTextFields:
- (id) tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSView *v = [[NSView alloc] init];
NSTextField *t1 = [[NSTextField alloc] init];
[t1 setStringValue:#"test1"];
NSTextField *t2 = [[NSTextField alloc] init];
[t1 setStringValue:#"test2"];
[v addSubview:t1];
[v addSubview:t2];
return v;
}
It seems that nothing happens, even if this code gets executed. I am not using the column identifier, I just want to return a custom view as a row.
This is the result:
What am I doing wrong?
This view will be very custom and large, so I cannot rely on Apple's "default" cell views.
Thank you!
View-based is a different than cell-based.
All that is different is replacing the "id" return value to "NSView".
Change this:
- (id)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
To this:
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
This is given the assumption you are running 10.7, and you are actually going to return an NSView.
A few things to check:
Does your NSTableView have its delegate set to the class that
implements the NSTableViewDelegate protocol? (I ask because
tableView:viewForTableColumn:row: is a delegate method whereas the
tableView:objectValueForTableColumn:row: is a data source method.)
Are there any bindings that are set in IB? Check mainly for bindings
to the NSTableView content binding and to the provided view's
subviews (usually the text field.)
Do you implement the numberOfRowsInTableView: method from the
NSTableViewDataSource protocol and does it return a nonzero integer?
Finally, you might have a look at the Table View Programming Guide chapter on "Populating View-Based Table Views Programmatically" in the documentation.

(OS X) Programmatically bound NSTableView does not display values

I created a viewController with a tableView and set the identifier of the only column to "name". Then I created an arrayController, bound it to a NSManagedObjectContext and set the right entity name.
When I now load the viewController, the tableView does display the correct amount of row. But unfortunately the cells do not contain the value of the NSManagedObjects value for the key name.
What do I have to implement in my NSManagedObject subclass or in the viewController (which is the tableViews viewController)?
I'd like to show you some code, but I don't know what could be helpful here, because it's more an conceptional question... So I'll post code as requested in comments.
UPDATE
This is the code I'm using to bind the arrayController tho the tableView:
[_tableView bind:NSContentBinding toObject:_arrayController withKeyPath:#"arrangedObjects.name" options:nil];
To inspect what the tableView gets, I added this line (after adding property called "content"):
[self bind:NSContentBinding toObject:_arrayController withKeyPath:#"arrangedObjects.name" options:nil];
In the setter I got an array containing NSString instances. But the tableView still does not display any values...
I finally used the standard NSTableViewDataSource protocol:
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [[_arrayController arrangedObjects] count];
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return [[[_arrayController arrangedObjects] objectAtIndex:row] valueForKey:[tableColumn identifier]];
}
I think this is a solid solution, though. I might became obsessed by the -bind:toObject:withKeyPath:options: idea.

iOS - Connect UITableViewCell to another ViewController Programmatically

I have programmatically created a tableView populated it with some rows. However, I was wondering upon tapping one of these cells how could I navigate to another view controller while passing data to the other viewController as well?
This is what I filled each cell with:
cell.textLabel.text = [NSString stringWithFormat:#"#%#", currentAccount.username];
How do I pass currentAccount.username to another viewController I just created? I am not using storyboards as I had created the UITableView programmatically. However, I have created another view controller called FeedViewController.
In your table view delegate method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
you would instantiate your FeedViewController, pass any data to it using its properties and then display it.
Something like:
FeedViewController* feedVC = [[FeedViewController alloc] init];
feedVC.username = currentAccount.username
[self presentViewController:feedVC animated:YES completion:nil];

Customized NSTableCellView's IBOutlet is null

I have a NSTableView, its data source and delegate have been set. And I want to customize the cell, so I dragged a view-based cell view from the library. Then I created a class ServiceCell which inherits from NSTableCellView in order to fully control my special cell. After that, I control-drag from the nib file to the cell class to create the IBOutlet properties of the image and text field in the cell.
In the NSTableView's delegate methods, I wrote this:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
// Get a new ViewCell
ServiceCell *cellView = [tableView makeViewWithIdentifier:#"ServiceCell" owner:self];
NSLog(#"Field = %#", cellView.textField); //which turns out to be null!!!
if( [tableColumn.identifier isEqualToString:#"ServiceColumn"] )
{
cellView.serviceImage.image = nil;
cellView.nameLabel.stringValue = #"Hello";
return cellView;
}
return cellView;
}
As you can see, the text field is null! But makeViewWithIdentifier: has found the cell in Interface Builder and displayed the cell in the app window. I just cannot set it's value, Why?
The problem is you are accessing your textfield but not accessing its textvalue. Try your log statement like this below:-
NSLog(#"Field = %#", cellView.textField.stringValue);
in Table view select cell and give identifier name (same as you are using in code, for your snipped it will be #"ServiceCell"), your code part is right it will work.

Delegate events for NSTextField in a view-based NSOutlineView?

I have a flawless functioning view-based NSOutlineView with a proper set-up datasource in my project. Now I want to allow the user to change certain entries. So I made the NSTextField in the IB editable. For a cell-based NSOutlineView you can use the delegate method outlineView:setObjectValue:forTableColumn:byItem: however it's not available for a view-based NSOutlineView as stated in the header file for the NSOutlineViewData protocol:
/* View Based OutlineView: This method is not applicable.
*/
(void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
So I searched for another delegate method and found outlineView:shouldEditTableColumn:item:. However this delegate method doesn't get fired. Probably because I'm not editing a cell.
So my question is: Is there any other way to notice when a row changed than having a delegate for each NSTextField?
You are correct that your text field needs to be editable in Interface Builder.
Next, make your controller conform to NSTextFieldDelegate. Then, set the delegate for the text field in outlineView:viewForTableColumn:item:, like so:
tableCellView.textField.delegate = self
Here's a simplified example, where you've implemented the method for returning the table cell view for an item for your outline view.
-(NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
NSTableCellView *tableCellView = [outlineView makeViewWithIdentifier:#"myTableCellView" owner:self];
MyItem *myItem = (MyItem *)item; // MyItem is just a pretend custom model object
tableCellView.delegate = self;
tableCellView.textField.stringValue = [myItem title];
tableCellView.textField.delegate = self;
return result;
}
Then, the controller should get a controlTextDidEndEditing notification:
- (void)controlTextDidEndEditing:(NSNotification *)obj
{
NSTextField *textField = [obj object];
NSString *newTitle = [textField stringValue];
NSUInteger row = [self.sidebarOutlineView rowForView:textField];
MyItem *myItem = [self.sidebarOutlineView itemAtRow:row];
myItem.name = newTitle;
}
Well, it seems like Apple wants us to use the delegate methods of each NSTextField as stated here:
This method is intended for use with cell-based table views, it must not be used with view-based table views. Instead target/action is used for each item in the view cell.
So there's currently no other way to do this.