Reputation: 5569
I currently have a tableview, with cell views which have NSTextFields inside of them. Currently, on row select, I'm sending the cell view the following message with the hope of granting the NSTextView in the cell view first responder status:
- (void)notifyOfSelectionInWindow:(NSWindow *)window {
[[self textField] setEditable:YES];
[[self textField] setSelectable:YES];
// make textField (textView) first responder
[[self textField] selectText:nil];
[[[self textField] currentEditor] setSelectedRange:NSMakeRange([[[self textField] stringValue] length], 0)];
}
Because I don't want the NSTextFields to be editable when the row they are in isn't selected, I also do this in my custom NSTextField subclass:
- (void)textDidEndEditing:(NSNotification *)notification {
[self setEditable:NO];
[self setSelectable:NO];
[super textDidEndEditing:notification];
}
Selection update code: (note that I'm also changing row heights here)
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row {
// get the table veiw to animate/recalculate height of row
NSMutableIndexSet *changedRows = [NSMutableIndexSet indexSet];
[changedRows addIndex:row];
[changedRows addIndex:[tableView selectedRow]];
[tableView noteHeightOfRowsWithIndexesChanged:changedRows];
[rowView notifyOfSelectionInWindow:[self window]];
// ^ this in turn calls a method of the same name of the corresponding cell view
return YES;
}
Problem is, this works only half of the time. The first time I try selecting a row, first responder status returns to the table view. The second time, it works perfectly, and the Text field has focus. The third time, it breaks again. The fourth - it's perfect! For some strange reason, the code only works every other time...
Anyone have any idea why this is so? Any enlightening feedback is much appreciated.
Upvotes: 2
Views: 1010
Reputation: 25740
When switching from from textField to textField in a tableView , events are called in what is an unexpected order (until you think about it).
The problem here is the order that your delegate methods are being called.
Let's say that you are going from textField1 to textField2.
Once textField1 is already active and you click on textField2, they get called like this:
textShouldBeginEditing (textField2)
textShouldEndEditing (textField1)
textDidEndEditing (textField1)
textDidBeginEditing (textField2)
Because textShouldBeginEditing
is called before textDidEndEditing
(because it needs to make sure that it can select the row before it gives up its' old one) you need to update your self.textField
in textDidBeginEditing
instead.
Upvotes: 2