Illegal NSTableView data source


After entering the code from the book:

  1. Click Run.
    App compiles and TahDoodle launches. The window appears as expected.

  2. Click Insert.
    The log window posts that createNewItem: was called. (I added one NSLog statement to help debug.)
    Then I get this message:

*** Illegal NSTableView data source (<BNRDocument: 0x10013b7b0>). Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:

The methods are implemented. I even updated them with the errata.

This is the interface file:

[code]#import <Cocoa/Cocoa.h>

@interface BNRDocument : NSDocument
NSMutableArray *todoItems;
IBOutlet NSTableView *itemTableView;

  • (IBAction)createNewItem:(id)sender;

This is the implementation file:

[code]#import “BNRDocument.h”

@implementation BNRDocument

#pragma mark - NSDocument Overrides

  • (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 @“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”];
    NSLog(@“Item created”);
    // -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 teh application whether or not the document
    // had unsaved changes. NSChangeDone flags the document as saved.
    [self updateChangeCount:NSChangeDone];

#pragma mark Data Source Methods

// Even though I have implemented these methods, I am getting errors when I call creatNewItm that say
// NSTableView data source is illegal and that I must implement these two methods

  • (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView{
    // 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 obejcts in the array
    return [todoItems count];

  • (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];

  • (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
    if (!todoItems) {
    todoItems = [NSMutableArray array];

    NSData *data = [NSPropertyListSerialization dataWithPropertyList:todoItems
    options:0 //Was NSPropertyListMutableContainers when printed
    return data;

  • (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
    todoItems = [NSPropertyListSerialization propertyListWithData:data
    options:NSPropertyListMutableContainers //Was 0 when printed
    return (todoItems != nil);


I am running Xcode 4.2.1 Build 4D502 on Mac OS X v10.7.2


You are missing:

- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex