gdubs
gdubs

Reputation: 2754

Objective C Dynamic NSDictionary for UI Table View divided by Section Headers

So this is based off of my question here

objective c when to use NSDictionary instead of NSArray

Apologies for the noob questions. I just started learning objective c and I'm really confused.

- (void)viewDidLoad
{
    [super viewDidLoad];
    headers = [NSArray arrayWithObjects:@"Header Section 1 (H1)", @"Header Section 2 (H2)", nil];
    events = [NSArray arrayWithObjects:@"H1 Content 1", @"H1 Content 2", nil];
    myInfo = [NSArray arrayWithObjects:@"H2 Content 1", @"H2 Content 2", @"H2 Content 3", nil];

    menuDetails = [[NSMutableDictionary alloc] init];
    for(NSString *event in events){
        [menuDetails setValue:event forKey:@"Header Section 1 (H1)"];
    }

    for(NSString *info in myInfo){
        [menuDetails setValue:info forKey:@"Header Section 1 (H2)"];
    }
}


-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return [[menuDetails allKeys] count];
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
    return [[[menuDetails allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]objectAtIndex:section];
}
  1. Wanted to limit this for the First Section but not on the 2nd section

    -(NSInteger)tableView:(UITableView *)tableview numberOfRowsInSection:(NSInteger)section {
        return 5;
    }
    
  2. So I'm not really sure how to make this dynamic when I try to fill up the cells with this method. I'm not really sure how to make sure it selects the "Key" of the section the specific cell is at (blocked line) :


-(UITableViewCell *)tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath {
    static NSString *CellIdentifier = @"OptionCellIdentifier";

        MenuOptionTableCell *cell = (MenuOptionTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        if(cell == nil){
            NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"OptionCellIdentifier" owner:self options:nil];
            cell = [nib objectAtIndex:0];
        }

        NSDictionary *menuItem = [[menuDetails valueForKey:[[[menuDetails allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];

        cell.optionName.text = [menuItem objectForKey:@"Events"];

        return cell;
    }

EDIT: GAAAHHH, the formatting is killing me. It won't get inside the code markup

This is where Idk what to do:

cell.optionName.text = [menuItem objectForKey:@"Events"];

So what I wanted to happen is:

Upvotes: 0

Views: 3170

Answers (2)

Sam T
Sam T

Reputation: 196

I would do this by first creating a "MyMenuSection" object as follows;

@interface MyMenuSection : NSObject {
    NSString *title;
    NSMutableArray *rows;
}

@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSMutableArray *rows;

@end

@implementation

@synthesize title;
@synthesize rows;

@dealloc {
    [title release];
    [rows release];
    [super dealloc];
}

@end

Then in your viewDidLoad (or wherever you decide to inialize/assign the data) you would do this;

-(void)viewDidLoad
{
    [super viewDidLoad];

    NSMutableArray menuDetails = [NSMutableArray array];

    MyMenuSection section = [[MyMenuSection alloc] init];
    section.title = @"Header Section 1 (H1)";
    [section.rows addObjects:@"H1 Content 1", @"H1 Content 2", nil];
    [menuDetails addObject:section];
    [section release];

    section = [[MyMenuSection alloc] init];
    section.title = @"Header Section 2 (H2)";
    [section.rows addObjects:@"H2 Content 1", @"H2 Content 2", @"H2 Content 3", nil];
    [menuDetails addObject:section];
    [section release];

    self.menuDetails = menuDetails;
    [menuDetails release];

}

Then your UITableView data and delegate callbacks would look like this;

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [menuDetails count];
}


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section == 0) {
        return 2;
    } else {
        return [[(MyMenuSection *)[menuDetails objectAtIndex:indexPath.section] rows] count];
    }
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [(MyMenuSection *)[menuDetails objectAtIndex:section] title];
}

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

    static NSString *cellIdentifier = @"OptionCellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if(cell == nil){
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"OptionCellIdentifier" owner:self options:nil];
        cell = [nib objectAtIndex:0];
    }

    cell.optionName.text = (NSString *)[[(MyMenuSection *)[menuDetails objectAtIndex:indexPath.section] rows] objectAtIndex:[indexPath.row]];

    return cell;

}

YMMV, Happy Coding

Upvotes: 1

joeByDesign
joeByDesign

Reputation: 133

Sounds like you're over thinking things here. My biggest recommendation here would be to get rid of all your separate arrays and start nesting them within each other. By that I mean make menuItems a NSArray of your arrays events and myInfo.

This will make it easier for you later on to get your dynamic row count using .count.

example:

events = [NSArray arrayWithObjects:@"H1 Content 1", @"H1 Content 2", nil];
myInfo = [NSArray arrayWithObjects:@"H2 Content 1", @"H2 Content 2", @"H2 Content 3", nil];

NSArray *menuItems = [NSArray arrayWithObjects:events, myInfo, nil];

Now when you call the array in

-(NSInteger)tableView:(UITableView *)tableview numberOfRowsInSection:(NSInteger)section{
    NSArray *tempArray = [NSArray objectAtIndex: section];
    return tempArray.count;
}

As for pulling the cell names later on.

cell.optionName.text = [[menuItem objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];

Upvotes: 1

Related Questions