Thanks in advance everyone!
I’ve quite thoroughly gone over the code and interface builder connections in this chapter and I’m practically certain that I have everything right. Despite this, when running TahDoodle I still can’t add text to the text field. The “Add Task” button works fine and creates a default “Table View Cell” task when clicked, but when I click or double click on the text bar to add a named task the cursor doesn’t appear. Thereafter when attempting to type my computer simply produces an error sound. I’m using Xcode 7.2.1. What am I missing?
Here is my code:
Document.h
#import <Cocoa/Cocoa.h>
@interface Document : NSDocument
<NSTableViewDataSource>
@property (nonatomic) NSMutableArray *tasks;
@property (nonatomic) IBOutlet NSTableView *taskTable;
- (IBAction)addTask:(id)sender;
@end
Document.m
#import "Document.h"
@interface Document ()
@end
@implementation Document
#pragma mark - NSDocument Overrides
- (instancetype)init {
self = [super init];
if (self) {
// Add your subclass-specific initialization here.
}
return self;
}
- (void)windowControllerDidLoadNib:(NSWindowController *)aController {
[super windowControllerDidLoadNib:aController];
// Add any code here that needs to be executed once the windowController has loaded the document's window.
}
+ (BOOL)autosavesInPlace {
return YES;
}
- (NSString *)windowNibName {
// Override returning the nib file name of the document
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
return @"Document";
}
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
// // Insert code here to write your document to data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning nil.
// // You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
// [NSException raise:@"UnimplementedMethod" format:@"%@ is unimplemented", NSStringFromSelector(_cmd)];
// return nil;
//This method is called when out document is being saved. You are expected to hand the caller an NSData object wrapping our data so that it can be written to the disk. If there is noa rray write out an empty array
if (!self.tasks) {
self.tasks = [NSMutableArray array];
}
// pack the tasks array into an NSData object
NSData *data = [NSPropertyListSerialization
dataWithPropertyList: self.tasks
format:NSPropertyListXMLFormat_v1_0
options:0
error];
// Return the newly packahed data-object
return data;
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
// // Insert code here to read your document from the given data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning NO.
// // You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
// // If you override either of these, you should also override -isEntireFileLoaded to return NO if the contents are lazily loaded.
// [NSException raise:@"UnimplementedMethod" format:@"%@ is unimplemented", NSStringFromSelector(_cmd)];
// return YES;
// This method is called when a document is being
// You are handed an NSData object and expected to pull our data out of it
// Extract the tasks
self.tasks = [NSPropertyListSerialization
propertyListWithData: data
options: NSPropertyListMutableContainers
format:NULL
error];
// return success or failure depending on the success of the above call
return (self.tasks != nil);
}
# pragma mark - Actions
-(void) addTask:(id)sender
{
// If there is not an array yet, create one
if (!self.tasks) {
self.tasks = [NSMutableArray array];
}
[self.tasks 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
[self.taskTable reloadData];
// -updateChangecount: tells the application whether or not the document has unsaved changes, NSChangeDone flags the document as unsaved
[self updateChangeCount:NSChangeDone];
}
#pragma mark Data Source Methods
-(NSInteger)numberOfRowsInTableView:(NSTableView *)tv
{
// this table view displays the tasks array so that the number of entries in the table view will be the same as the number of objects int the array
return [self.tasks count];
}
-(id)tableView:(NSTableView *)tableView
objectValueForTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row
{
// Return the item from tasks that corresponds to the cell that the table view wants to display
return [self.tasks objectAtIndex:row];
}
-(void)tableView:(NSTableView *)tableView
setObjectValue:(id)object
forTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row
{
// When the user changes a task on the table view update the tasks array
[self.tasks replaceObjectAtIndex:row withObject:object];
// And then flag the document as having unsaved changes
[self updateChangeCount:NSChangeDone];
}
@end