Chapter 6, second challenge. I need some help/guidance


#1

To whom it may concern,

I am stuck on the second challenge from chapter six. I can build and run the App, but when I type in a task and click the ‘Add’ button, nothing happens.

Here is my AppController header

#import <Cocoa/Cocoa.h>

@interface TaskListController : NSObject
{
	IBOutlet NSTextField *textField;
	IBOutlet NSTableView *listView;
	NSMutableArray *things;
}

-(IBAction)addNewItem:(id)sender;

@end

Here is my AppController.m file

#import "TaskListController.h"

@implementation TaskListController

-(id)init
{
	self = [super init];
	if(self)
	{
		things = [[NSMutableArray alloc] init];
	}
	return self;
}

-(IBAction)addNewItem:(id)sender
{
	NSString *item = [textField stringValue];
	if([item length] == 0)
	{
		NSLog(@"String is zero-length!");
		return;
	}
	[things addObject: item];
}

-(int)numberOfRowsInTableView:(NSTableView *)tv
{
	return [things count];
}

-(id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
	NSString *v = [things objectAtIndex: row];
	return v;
}

@end

Help?


#2

I got it!!

Here are the .h and .m files for MY working solution:

TaskListController.h

#import <Cocoa/Cocoa.h>

@interface TaskListController : NSObject
{
	IBOutlet NSTextField *textField;
	IBOutlet NSTableView *listView;
	NSMutableArray *things;
}

-(IBAction)addNewItem:(id)sender;
-(IBAction)removeItem:(id)sender;
-(IBAction)replaceItem:(id)sender;

@end
#import "TaskListController.h"

@implementation TaskListController

-(id)init
{
	self = [super init];
	if(self)
	{
		things = [[NSMutableArray alloc] init];
		NSLog(@"init");
	}
	return self;
}

-(IBAction)addNewItem:(id)sender
{
	NSString *item = [textField stringValue];
	NSLog(@"String says: %@", item);
	if([item length] == 0)
	{
		NSLog(@"String is zero-length!");
		return;
	}
	[things addObject: item];
	[listView reloadData];
}

// remove a selected item from the list
-(IBAction)removeItem:(id)sender
{
	if([things count] == 0)
	{
		NSLog(@"Nothing stored.");
		return;
	}
	int r = [listView selectedRow];
	[things removeObjectAtIndex: r];
	[listView reloadData];
}

// replace selected item with currect entry in textfield
-(IBAction)replaceItem:(id)sender
{
	if([things count] == 0)
	{
		NSLog(@"Nothing stored.");
		return;
	}
	NSString *item = [textField stringValue];
	if([item length] == 0)
	{
		NSLog(@"String is zero-length!");
		return;
	}
	int r = [listView selectedRow];
	[things replaceObjectAtIndex: r withObject: item];
	[listView reloadData];
}

-(int)numberOfRowsInTableView:(NSTableView *)tv
{
	NSLog(@"Number of rows: %d", [things count]);
	return [things count];
}

-(id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
	NSLog(@"Rows: %d", [things count]);
	NSString *v = [things objectAtIndex: row];
	NSLog(@"Item: %@", v);
	return v;
}

@end

Also, I noticed it made no difference whether or not the controller was a delegate of the NSTableView or not. Anyone wanna explain for me?


#3

Ok, slightly modified the .m file:

TaskListController.m

#import "TaskListController.h"

@implementation TaskListController

-(id)init
{
	self = [super init];
	if(self)
	{
		things = [[NSMutableArray alloc] init];
		NSLog(@"init");
	}
	return self;
}

-(IBAction)addNewItem:(id)sender
{
	NSLog(@"String says: %@", [textField stringValue]);
	if([[textField stringValue] length] == 0)
	{
		NSLog(@"String is zero-length!");
		return;
	}
	[things addObject: [textField stringValue]];
	[listView reloadData];
}

// remove a selected item from the list
-(IBAction)removeItem:(id)sender
{
	if([things count] == 0)
	{
		NSLog(@"Nothing stored.");
		return;
	}
	[things removeObjectAtIndex: [listView selectedRow]];
	[listView reloadData];
}

// replace selected item with currect entry in textfield
-(IBAction)replaceItem:(id)sender
{
	if([things count] == 0)
	{
		NSLog(@"Nothing stored.");
		return;
	}
	if([[textField stringValue] length] == 0)
	{
		NSLog(@"String is zero-length!");
		return;
	}
	[things replaceObjectAtIndex: [listView selectedRow] withObject: [textField stringValue]];
	[listView reloadData];
}

-(int)numberOfRowsInTableView:(NSTableView *)tv
{
	NSLog(@"Number of rows: %d", [things count]);
	return [things count];
}

-(id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
	NSLog(@"Rows: %d", [things count]);
	NSLog(@"Item: %@", [things objectAtIndex: row]);
	return [things objectAtIndex: row];
}

-(void)dealloc
{
	[things release];
	[super dealloc];
}

@end

#4

I am having problems with the editing of the cells in the NSTableView.
My approach seems to be different from you guys. I try to edit it directly in the table with the method:

-(BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor {
NSLog(@“click”);
return [super control:control textShouldEndEditing:fieldEditor];
}

but every time i run it i get:

2010-06-26 11:37:51.739 Challenge_To-Do-List[34218:10b] respondsToSelector: control:isValidObject:
2010-06-26 11:37:51.739 Challenge_To-Do-List[34218:10b] respondsToSelector: control:textShouldEndEditing:
2010-06-26 11:37:51.740 Challenge_To-Do-List[34218:10b] click
2010-06-26 11:37:51.740 Challenge_To-Do-List[34218:10b] *** -[AppController control:textShouldEndEditing:]: unrecognized selector sent to instance 0x13b370
2010-06-26 11:37:51.741 Challenge_To-Do-List[34218:10b] *** -[AppController control:textShouldEndEditing:]: unrecognized selector sent to instance 0x13b370

can somebody help me?


#5

Hi Zeroartist,

I was having trouble making the table editable as well. What solved it for me was implementing the following method (which is introduced earlier in the chapter on page 100):

- (void)tableView:(NSTableView *)aTableView
   setObjectValue:(id)anObject
   forTableColumn:(NSTableColumn *)aTableColumn
              row:(int)rowIndex;

Hope this helps.

  • Henry