views:

556

answers:

2

In a UITableViewController subclass, there are some methods that need to be implemented in order to load the data and handle the row selection event:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1; //there is only one section needed for my table view
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {              
    return [myList count]; //myList is a NSDictionary already populated in viewDidLoad method
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease ];
    }

    // indexPath.row returns an integer index, 
    // but myList uses keys that are not integer, 
    // I don't know how I can retrieve the value and assign it to the cell.textLabel.text


    return cell;
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    // Handle row on select event, 
    // but indexPath.row only returns the index, 
    // not a key of the myList NSDictionary, 
    // this prevents me from knowing which row is selected


}

How is NSDictionary supposed to work with TableView?

What is the simplest way to get this done?

+5  A: 

I do not understand why you want to use a dictionary (which is inheritly unordered) for a task that requires answers to ordered questions (rows), but i take it that you have a dictionary already from somewhere and cannot change that. If that is the case, you have to define an order you want to display the keys in, thereby deriving an array implicitly. One way to do this is alphabetically order another one is the following:

// a) get an array of all the keys in your dictionary
NSArray* allKeys = [myList allKeys];
// b) optionally sort them with a sort descrriptor (not shown)
// c) get to the value at the row index
id value = [myList objectForKey:[allKeys objectAtIndex:indexPath.row]];

value is now the object selected in the case of tableView:didSelectRowAtIndexPath: or the object you need for your cell processing in tableView:cellForRowAtIndexPath:

If the underlying NSDictionary changes, you do have to reload ([myTable reload] or the like) the UITableView.

NSSplendid
Your solution is simple enough for me.
bobo
Simple solution but this helped me out a lot!
stitz
+2  A: 

Yes. Here is how we have done it:

In our xml parser we have this method which loads the xml into a dictionary called dict:

-(NSDictionary *)getNodeDictionary:(Node *)node {
    if (node->level == 0) return xmlData;
    else {
        NSDictionary *dict = xmlData;
        for(int i=0;i<node->level;i++) {
            if ([[dict allKeys] containsObject:SUBNODE_KEY])
                dict = [[dict objectForKey:SUBNODE_KEY]   objectAtIndex:*(node->branches+i)];
        }
        return dict;
    }
}

And this method

-(NSDictionary *)getDataForNode:(Node *)node {
NSDictionary* dict = [[self getNodeDictionary:node] copy];
return dict;

}

In the RadioData class we have an instance variable:

Node *rootNode;

and a bunch of methods

-(Node *)getSubNodesForNode:(Node *)node;
-(Node *)getSubNodeForNode:(Node *)node atBranch:(NSInteger)branch;
-(Node *)getParentNodeForNode:(Node *)node;
-(NSInteger)getSubNodeCountForNode:(Node *)node;
-(NSDictionary *)getDataForNode:(Node *)node;

and a property

@property (nonatomic) Node *rootNode;

Finally in the ViewController when we init the frame we use:

radioData = data;
curNode = data.rootNode;

and inside cellForRowAtIndexPath we have:

Node* sub = [radioData getSubNodeForNode:curNode atBranch:indexPath.row];
NSDictionary* dets = [radioData getDataForNode:sub];    

and in didSelectRowAtIndexPath:

    Node* node = [radioData getSubNodeForNode:curNode atBranch:indexPath.row];
NSDictionary* data = [radioData getDataForNode:node];

This is probably more than you wanted but that is the general outline.

----------- EDIT -----------

I ran across this tutorial that may be more understandable.

Michael
Thanks a lot for your solution. But it's a complicated one for me.
bobo
Yes... its a bit complex but the example is from a rather complex app. Unfortunately, I don't have a simpler example at hand. This should, however, give you a starting point. Perhaps using arrays might be easier.
Michael