Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,128
1
Scotland
Hey i am trying to echo out a an array into a table, i've been using a book on cocoa but think i am going wrong somewhere. Now i know from my nslog that i am filling up the array but its not going into my nstableview.

This is my .m
Code:
#import "UsersTable.h"


@implementation UsersTable

- (void)userName:(NSMutableArray *)a
{
	// Connect to the database
    MysqlConnection *connection = [MysqlConnection connectToHost:@"localhost"
															user:@"root"
														password:@""
														  schema:@"test_db"
														   flags:MYSQL_DEFAULT_CONNECTION_FLAGS];
	
	// Fetch the users from the database
	MysqlFetch *userFetch = [MysqlFetch fetchWithCommand:@"select username, email from users" onConnection:connection];
	
	
	NSMutableArray *users; // Create the users array pointer
	users = [[NSMutableArray alloc] init]; // Allocate the array to the memory
	
	// Create the userArray for the table
	for (NSDictionary *userRow in userFetch.results) {
		NSString *user = [userRow objectForKey: @"username"];
		[users addObject:user];
	}

}

@synthesize userName;

@end

And this is my .h
Code:
#import <Cocoa/Cocoa.h>
#import "MysqlConnection.h"
#import "MysqlCommitException.h"
#import "MysqlRollbackException.h"
#import "GC_MYSQL_BIND.h"
#import "MysqlFetch.h"
#import "MysqlFetchField.h"

@interface UsersTable : NSObject {
	NSWindow *window;
	NSString *userName;
}
@property (readwrite, copy) NSString *userName;

@end


In my xib i have a NSTableView that is bound to array controller in the drop down, controller key is section and model key path is userName.

My Array controller is in class mode, with a class name of usersArray and userName is in the key.
 
I'm mostly iPhone focussed now so this may be a bit wrong but I think you need to either insert via the array controller (instead of inserting directly to the array) or inform the array controller you have inserted. I'd look at add: in NSArrayController.

Also why are you creating the array via alloc/init? Is this not in the xib? Or how is this connected to the array controller?
 
Sorry i am quite new to Objective C and even more new with Cocoa i don't quite understand what your asking.

So what i'll do is explain what the application is meant to do with this array.

Firstly inside - (void)userName:(NSMutableArray *)a { -- } i am connecting to my MySQL database and querying the results of a table called users in my test database, i know there are 15 entries in this. So with a NSLog at this stage it would return 15 usernames.

Now what i want to do with this data is simply put it into a NSTableView and from what i understand it needs to go into a NSArray to be used with the Array Controller.
 
Now what i want to do with this data is simply put it into a NSTableView and from what i understand it needs to go into a NSArray to be used with the Array Controller.

Yep, that all sounds fine. But somewhere you need to connect the controller to the array. This is quite hard if the array does not exist the the method is called. Which is why I suggested the array should exist from the start and be connected to the controller in the xib file.
 
Well I would try creating an instance of NSMutableArray in Interface Builder, attach the controller to it and create an IBOutlet to allow you to reference the array you created in IB.
 
Ok i have tried the following but still no joy.

My .h
Code:
#import <Cocoa/Cocoa.h>
#import "MysqlConnection.h"
#import "MysqlCommitException.h"
#import "MysqlRollbackException.h"
#import "GC_MYSQL_BIND.h"
#import "MysqlFetch.h"
#import "MysqlFetchField.h"

@interface UsersTable : NSObject {
	IBOutlet NSMutableArray *UsersArray;
	NSWindow *window;
	NSString *userName;
}
@property (readwrite, copy) NSString *userName;

@end

my .m
Code:
#import "UsersTable.h"


@implementation UsersTable

- (id)userName
{
	// Connect to the database
    MysqlConnection *connection = [MysqlConnection connectToHost:@"localhost"
															user:@"root"
														password:@""
														  schema:@"test_db"
														   flags:MYSQL_DEFAULT_CONNECTION_FLAGS];
	
	// Fetch the users from the database
	MysqlFetch *userFetch = [MysqlFetch fetchWithCommand:@"select username, email from users" onConnection:connection];
	
	// Create the userArray for the table
	for (NSDictionary *userRow in userFetch.results) {
		NSString *user = [userRow objectForKey: @"username"];
		[UsersArray addObject:user];
	}
	
	return UsersArray;
}

@synthesize userName;

@end

Now in Interface builder i have a NSMutableArray with a class of "Users Table", A ArrayContoller that is mode "class" classname of UsersTable and content --> Users Table.

And my first text cell in my NSTableView is bound to array controller with a model key path of userName


updated with the actual code.
 
You are still creating a new NSMutableArray that nothing is connected to and inserting the data into that instead of using the one that you created in the xib. You need to stop and think more logically about what objects are in your program and how they are connected. Draw it out on paper. You'll soon see whats going on.
 
Im going to call it a night, wile it would be nice to finally get something in a real application window i am not going to make any headway half asleep. Thanks for the help tonight, will see if re reading the chapters in this book help before i try again.
 
Yep this is a Mac application, mite port to iOS in the future but i do not believe iOS supports the garbage collector.
 
Try linking the NSMutableArray in IB to the Mutable Array in your class, via an IBOutlet. As far as I can tell though you don't need the NSMutableArray in IB at all, you could have an NSArrayController in your class linked to the on in IB, then call

Code:
[arrayController addObject:user];

And the users will appear in the table view. To then get at the contents of the ArrayController, you can call

Code:
NSArray *myArray = [arrayController arrangedObjects];

I've just done something similar so it's fresh in my brain.
 
Is there an example application floating around that demonstrates the NSTableView, i am currently reading though the Apple documentation yet some of it still seems to make little sense.
 
Is there an example application floating around that demonstrates the NSTableView, i am currently reading though the Apple documentation yet some of it still seems to make little sense.

A lot of examples are pre-bindings with data source protocols and so on. These are very good, more recent, examples with bindings

(1st search result in Google for "NSTableView bindings example")
 
Ok i followed a video tutorial witch was great at showing how the connections are made in interface builder. http://www.youtube.com/watch?v=Oj7CrJi7ylA

However it seems mine does not work, my console complains about:
Code:
*** Illegal NSTableView data source (<TableViewAppDelegate: 0x100335350>).  Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:

However it works fine for the guy on the video, maybe i've got a spelling mistake or something i can't pick up. But the error indicates i missed something much larger.

Heres my .h
Code:
//
//  TableViewAppDelegate.h
//  TableView
//

#import <Cocoa/Cocoa.h>

@interface TableViewAppDelegate : NSObject <NSApplicationDelegate> {
    NSWindow *window;
    NSTableView *tableView;
    NSArrayController *arrayController;
}

@property (assign) IBOutlet NSWindow *window;
@property (assign) IBOutlet NSTableView *tableView;
@property (assign) IBOutlet NSArrayController *arrayController;


@end

And my .m
Code:
//
//  TableViewAppDelegate.m
//  TableView
//

#import "TableViewAppDelegate.h"

@implementation TableViewAppDelegate

@synthesize window;
@synthesize tableView;
@synthesize arrayController;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
	[arrayController addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"user1", @"name", @"Email Address", @"email", nil]];
  [arrayController addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"user2", @"name", @"Email Address 2", @"email", nil]];
  [tableView reloadData];
}
@end
 
Ok i followed a video tutorial witch was great at showing how the connections are made in interface builder. http://www.youtube.com/watch?v=Oj7CrJi7ylA

However it seems mine does not work, my console complains about:
Code:
*** Illegal NSTableView data source (<TableViewAppDelegate: 0x100335350>).  Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:

However it works fine for the guy on the video, maybe i've got a spelling mistake or something i can't pick up. But the error indicates i missed something much larger.

Yep. Bindings and using datasources are 100% different. You don't use them together.
 
Now i am more confused, why does it work in the video?

Was the way the video showed once legal code and has since been deprecated?
 
I didn't read all the postings but I noticed that you declared userName but are trying to use username - its all case sensitive...
 
Now i am more confused, why does it work in the video?

Was the way the video showed once legal code and has since been deprecated?

You can still use a data source. It just takes a lot more code: you have to implement the protocol and supply all the data to the table via the declared methods.
 
So do you know of any updated tutorial videos, screen casts demonstrating creating a NSTableView the right way?

I have tried asking round my lectuers but there all C++ guys and have never touched Cocoa, i myself am more fimilure with Ruby, PHP, and C.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.