NSArrayController creating, modifying and then selecting a new object
The main view of my NSPersistentDocument based application is a table view (bound to an NSArrayController) showing the list of records, below it there is an "add record" button. I want the button to cause the following (supposedly trivial) behavior.
- Create an new object
- Set some defaults to the new object (that are stored in the main document and not available globally)
- Add it to the table view.
Here are the things that I tried or dismissed:
- use the NSArrayController "add" action - problem: will not return the new object and implementation is deferred so it is impossible to modify the newly created object
- Override the init of the data class - will not work - I need to access data that is stored in the document class instance
- Subclass NSArrayController and override "newObject" - again - will not work because I need to access data that is stored in the document.
Following code "almost" worked:
- (IBAction)newRecord:(id)sender { MyDataClass *newRecord = [recordsArrayController newObject]; newRecord.setting1=self.defaultSetting1; newRecord.setting2=self.defaultSetting2; // ... etc... [recordsArrayController addObject:newRecord]; [recordsTable scrollRowToVisible:[recordsTable selectedRow]]; [newRecord开发者_Python百科 release]; }
This code actually works well, for unsaved documents. But if I save the document and re-open it then clicking on the add button results in the new record showing twice in the table. Obviously the "addObject" is redundant (although it works fine in unsaved documents) but without it the new object is not selected.
Simple case that should work:
MyDataClass *newRecord = [controller newObject];
// configure newRecord
[controller addObject:newRecord];
[newRecord release];
In order for the new object to be selected, the controller needs to have been configured for -setSelectsInsertedObjects:YES
previously.
But, there's an alternative which I'd consider more proper. Subclass NSArrayController like so (slighty pseudo-code):
@interface MyRecordController : NSArrayController
@property id recordSetting1;
@property id recordSetting2;
@end
@implementation MyRecordController
@synthesize recordSetting1;
@synthesize recordSetting2;
- (id)newObject
{
id result = [super newObject];
newRecord.setting1 = self.recordSetting1;
newRecord.setting2 = self.recordSetting2;
return result;
}
@end
So, your code then becomes:
- (IBAction)newRecord:(id)sender
{
recordsArrayController.recordSetting1 = self.defaultSetting1;
recordsArrayController.recordSetting2 = self.defaultSetting2;
[recordsArrayController add:self];
}
Really, all you need to do is modify your code to omit the addObject:
call. To make your new object selected, just do this:
[recordsArrayController setSelectedObjects:[NSArray arrayWithObject:newObject]];
before you do your call to swcrollRowToVisible:
. You're right that the addObject:
call is unneeded. As you've seen, it's ending up in the array controller twice.
Also, you won't need to call [newRecord release]
. The documentation says the object is retained by the array controller. It's not failing now because it's being retained a second time when you do addObject:
.
精彩评论