Now that you’ve got the user interface of your application created, configured, and connected, it’s time to get back to writing code. Click on BNRDocument.m in the project navigator to reopen it in the editor, and implement createNewItem:.
#import "BNRDocument.h" @implementation BNRDocument #pragma mark - NSDocument Overrides - (NSString *)windowNibName { return @"BNRDocument"; } #pragma mark - Actions - (IBAction)createNewItem:(id)sender { // If there's no array yet, go ahead and create one to store our new task if (!todoItems) { todoItems = [NSMutableArray array]; } [todoItems addObject:@"New Item"]; // -reloadData tells the table view to refresh and ask its dataSource // (which happens to be this BNRDocument object in this case) // for new data to display [itemTableView reloadData]; // -updateChangeCount: tells the application whether or not the document // has unsaved changes. NSChangeDone flags the document as unsaved. [self updateChangeCount:NSChangeDone]; }
Now implement the required table view data source methods (as defined by the NSTableViewDataSource protocol):
#pragma mark Data Source Methods - (NSInteger)numberOfRowsInTableView:(NSTableView *)tv { // This table view is meant to display the todoItems, // so the number of entries in the table view will be the same // as the number of objects in the array. return [todoItems count]; } - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { // Return the item from todoItems that corresponds to the cell // that the table view wants to display return [todoItems objectAtIndex:row]; } - (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { // When the user changes a to-do item on the table view, // update the todoItems array [todoItems replaceObjectAtIndex:row withObject:object]; // And then flag the document as having unsaved changes. [self updateChangeCount:NSChangeDone]; }
Build and run the program. TahDoodle will appear on the screen, and you can add and change to-do items. The big missing feature, however, is the ability to save and reopen a to-do list. To make this happen, you need to override the following methods inherited from BNRDocument’s superclass, NSDocument:
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError { // This method is called when our document is being saved // We are expected to hand the caller an NSData object wrapping our data // so that it can be written to disk // If there's no array, we'll write out an empty array for now if (!todoItems) { todoItems = [NSMutableArray array]; } // Pack our todoItems array into an NSData object NSData *data = [NSPropertyListSerialization dataWithPropertyList:todoItems format:NSPropertyListXMLFormat_v1_0 options:NSPropertyListMutableContainers error:outError]; // return our newly-packed NSData object return data; } - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError { // This method is called when a document is being loaded // We are handed an NSData object and expected to pull our data out of it // Extract our todoItems todoItems = [NSPropertyListSerialization propertyListWithData:data options:0 format:NULL error:outError]; // return success or failure depending on success of the above call return (todoItems != nil); }
Notice that for the first time, you’re implementing a method that takes in an NSError**. In this case, we are merely handing back the NSError generated by propertyListWithData:options:format:error:, but you could also create and hand back a new NSError as well, depending on the nature of the failure.
Build and run the application again. Now you can save and load task lists.