PDA

View Full Version : Help with NSTableView and NSMutableArray




Cabbit
Aug 31, 2010, 03:58 PM
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


#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

#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.



robbieduncan
Aug 31, 2010, 04:01 PM
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: (http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ApplicationKit/Classes/NSArrayController_Class/Reference/Reference.html#//apple_ref/occ/instm/NSArrayController/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?

Cabbit
Aug 31, 2010, 04:10 PM
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.

robbieduncan
Aug 31, 2010, 04:12 PM
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.

Cabbit
Aug 31, 2010, 04:17 PM
So this will sound silly but how do i make my array exist first. :o

robbieduncan
Aug 31, 2010, 04:19 PM
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.

Cabbit
Aug 31, 2010, 04:46 PM
Ok i have tried the following but still no joy.

My .h

#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

#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.

robbieduncan
Aug 31, 2010, 04:49 PM
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.

Cabbit
Aug 31, 2010, 05:06 PM
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.

Giuly
Aug 31, 2010, 06:51 PM
You have to implement the UITableViewDelegate (http://developer.apple.com/iphone/library/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html) protocol.

Catfish_Man
Aug 31, 2010, 06:57 PM
You have to implement the UITableViewDelegate (http://developer.apple.com/iphone/library/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html) protocol.

UI* is iPhone only. babyjenniferLB is presumably using bindings, which is a Mac-only technology.

Cabbit
Sep 1, 2010, 02:18 AM
Yep this is a Mac application, mite port to iOS in the future but i do not believe iOS supports the garbage collector.

knightlie
Sep 1, 2010, 03:22 AM
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

[arrayController addObject:user];

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

NSArray *myArray = [arrayController arrangedObjects];

I've just done something similar so it's fresh in my brain.

Cabbit
Sep 1, 2010, 04:56 AM
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.

robbieduncan
Sep 1, 2010, 05:10 AM
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 (http://homepage.mac.com/mmalc/CocoaExamples/controllers.html)

(1st search result in Google for "NSTableView bindings example")

Cabbit
Sep 1, 2010, 05:29 AM
No longer relevant.

Cabbit
Sep 4, 2010, 06:44 AM
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:

*** 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


//
// 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


//
// 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

robbieduncan
Sep 4, 2010, 07:10 AM
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:

*** 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.

Cabbit
Sep 4, 2010, 07:58 AM
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?

HomeBru Studios
Sep 4, 2010, 08:25 AM
I didn't read all the postings but I noticed that you declared userName but are trying to use username - its all case sensitive...

robbieduncan
Sep 4, 2010, 08:36 AM
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.

Cabbit
Sep 4, 2010, 09:21 AM
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.

Cabbit
Sep 4, 2010, 09:33 AM
I didn't read all the postings but I noticed that you declared userName but are trying to use username - its all case sensitive...

Post 17 is my current code, i've tried to simplify it till i can get the basics working.