6
votes

After adding a NSTableView to my xib on Xcode 4 I set it to have 4 columns. The 1st column is a simple column that will contain the name of an item. The other 3 are checkboxes. I dragged a Check Box Cell from the object library to the tableview.

I populate the table and the checkboxes get created and shown, however if I click on the nothing happens, I can't check or uncheck them. Furthermore, I don't even know how to do it by code.

How can I make this work: be able to check or uncheck the checkboxes and get their states from code.

I already saw this question and it didn't really answer my question.

Here is some of the code to take care of table, as requested:

- (int)numberOfRowsInTableView:(NSTableView *)tableView
{
    return (int)[myArray count];
}

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
    if([[tableColumn identifier] isEqualToString:@"col1"])
    {
       return[NSNumber numberWithInt:NSOffState];
    }    

    return [myArray objectAtIndex:row];
}

- (void)tableView:(NSTableView *)tableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
    NSLog(@"%d", [anObject boolValue]);
    if([[tableColumn identifier] isEqualToString:@"col1"])
    {
        NSLog(@"click col1");
    }        
    if([[tableColumn identifier] isEqualToString:@"col2"])
    {
        NSLog(@"click col2");
    }        

}

I just added more code. How do I set it to check/uncheck?

1
Could you edit your question and shows us the implementation of -tableView:setObjectValue:forTableColumn:row:? The implementation of -tableView:objectValueForTableColumn:row: will help, too. - user557219
What kind of objects are you inserting into the array? How do you map the contents of your objects to the four columns? Your code maps the whole object to the four columns. - user557219
I have a array with the strings that go on the 1st column. Then the rest I am stuck. see the code I just added. - Mr Aleph

1 Answers

8
votes

The model

You need to decide upon a model, i.e., how you’re going to represent the data that’s being shown on the table view. For example:

// SomeObject.h
#import <Foundation/Foundation.h>
@interface SomeObject
@property (copy) NSString *name;
@property (assign,getter=isVisible) BOOL visible;
@property (assign,getter=isOpaque) BOOL opaque;
@property (assign,getter=isAnimatable) BOOL animatable;
@end

// SomeObject.m
#import "SomeObject.h"
@implementation SomeObject
@synthesize name, visible, opaque, animatable;
- (void)dealloc {
    [name release];
    [super dealloc];
}
@end

The nib file

For the sake of this answer, give the table columns identifiers that match the property names in SomeObject.

Providing values from the model to the table view

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
    // Retrieve the model object corresponding to `row'
    SomeObject *obj = [myArray objectAtIndex:row];

    // Return the object property corresponding to the column
    if([[tableColumn identifier] isEqualToString:@"name"])
    {
        return obj.name;
    }
    // Since this method has return type `id', we need to box the
    // boolean values inside an `NSNumber' instance
    else if([[tableColumn identifier] isEqualToString:@"visible"])
    {
        return [NSNumber numberWithBool:obj.visible];
    }
    else if([[tableColumn identifier] isEqualToString:@"opaque"])
    {
        return [NSNumber numberWithBool:obj.opaque];
    }
    else if([[tableColumn identifier] isEqualToString:@"animatable"])
    {
        return [NSNumber numberWithBool:obj.animatable];
    }

    return nil;
}

Using values from the table view to update the model

- (void)tableView:(NSTableView *)tableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
    // Retrieve the model object corresponding to `row'
    SomeObject *obj = [myArray objectAtIndex:row];

    // Set the object property corresponding to the column
    if([[tableColumn identifier] isEqualToString:@"name"])
    {
        obj.name = anObject;
    }
    // Since the new value (`anObject') is an object, we need to
    // convert it to `BOOL' by sending it `-boolValue'
    else if([[tableColumn identifier] isEqualToString:@"visible"])
    {
        obj.visible = [anObject boolValue];
    }        
    else if([[tableColumn identifier] isEqualToString:@"opaque"])
    {
        obj.opaque = [anObject boolValue];
    }        
    else if([[tableColumn identifier] isEqualToString:@"animatable"])
    {
        obj.animatable = [anObject boolValue];
    }
}

It is possible to make this code simpler by using Key-Value Coding but that’s left as an exercise after you master table view data sources. :P