views:

43

answers:

1

I'm making a "simple" to-do-list project and running into a few bumps in the road. The problem is that my NSTableView is NOT showing the data from the NSMutableArray "myArray" and I don't know why that is. Can someone point out my mistake?

/*
 IBOutlet NSTextField *textField;
 IBOutlet NSTabView *tableView;
 IBOutlet NSButton *button;
 NSMutableArray *myArray;
 */

#import "AppController.h"


@implementation AppController


-(IBAction)addNewItem:(id)sender
{

    NSString *myString = [textField stringValue];

    NSLog(@"my stirng is %@",myString);
    myArray = [[NSMutableArray alloc] initWithCapacity:100];
    [myArray addObject:myString];

}

- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
    return [myArray count];
}
- (id)tableView:(NSTableView *)aTableView
objectValueForTableColumn:(NSTableColumn *)aTableColumn
            row:(int)rowIndex
{

    return [myArray objectAtIndex:rowIndex];
}

-(id)init
{
    [super init];
    [tableView setDataSource:self];
    [tableView setDelegate:self];

    NSLog(@"init");
    return self;
}

@end
+2  A: 

The problem is that in your -init method, your tableView variable will still be nil. When a nib file is loaded, it first creates and initializes all the objects declared in the nib and only then sets up the connections (outlets, bindings, actions) between them. Any initialization code of yours that depends on the various actions, outlets or bindings being set up needs to be placed in the -(void)awakeFromNib method not the -init method. You can also set the dataSource and delegate outlets of your table view right in Interface Builder, just by control-dragging from the tableView to your AppController in the main nib window, and choosing each outlet in turn.

Also, whenever you change your underlying data, you need to call [tableView reloadData] to get the tableView to reflect those changes. In you case, you'd need to call it in your -addNewItem: method. So, your code should look something like this:

@implementation AppController
- (id)init
{
    if (nil == (self = [super init])) return nil;
    myArray = [[NSMutableArray alloc] init];
    return self;
}
- (void)dealloc
{
    [myArray release];
    [super dealloc];
}
- (void)awakeFromNib
{
    // assuming you're not just setting up these outlets in IB
    [tableView setDataSource:self];
    [tableView setDelegate:self];
}
-(IBAction)addNewItem:(id)sender
{
    [myArray addObject:[textField stringValue]];
    [tableView reloadData];
}
// data source methods same as in your code
@end
Boaz Stuller
Not related to the asked question, but the init method is wrong. the returned value from [super init] needs to be assigned to self and you need to test to make sure self is not nil before allocating myArray.
JeremyP
You're right. I left it as-is because my coding style for that is a bit funny-looking, and I was worried it might be confusing. I'll edit it now to add it.
Boaz Stuller
thans for all the help. I didn't even know about the reloadData method. I need to read more about the classes that i'm using.
lampShade