Help with NSTableView and NSMutableArray

Discussion in 'Mac Programming' started by Cabbit, Aug 31, 2010.

  1. macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #1
    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.
     
  2. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    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?
     
  3. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #3
    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.
     
  4. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    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.
     
  5. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #5
    So this will sound silly but how do i make my array exist first. :eek:
     
  6. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #6
    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.
     
  7. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #7
    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.
     
  8. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #8
    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.
     
  9. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #9
    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.
     
  10. macrumors 68040

    Giuly

  11. macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #11
    UI* is iPhone only. babyjenniferLB is presumably using bindings, which is a Mac-only technology.
     
  12. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #12
    Yep this is a Mac application, mite port to iOS in the future but i do not believe iOS supports the garbage collector.
     
  13. macrumors 6502a

    Joined:
    Feb 18, 2008
    #13
    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.
     
  14. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #14
    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.
     
  15. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #15
    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")
     
  16. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
  17. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #17
    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
    
     
  18. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #18
    Yep. Bindings and using datasources are 100% different. You don't use them together.
     
  19. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #19
    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?
     
  20. macrumors member

    HomeBru Studios

    Joined:
    Jun 4, 2008
    #20
    I didn't read all the postings but I noticed that you declared userName but are trying to use username - its all case sensitive...
     
  21. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #21
    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.
     
  22. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #22
    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.
     
  23. thread starter macrumors 68020

    Cabbit

    Joined:
    Jan 30, 2006
    Location:
    Scotland
    #23
    Post 17 is my current code, i've tried to simplify it till i can get the basics working.
     

Share This Page