简体   繁体   中英

Sectioned UITableview from plist

I have a plist file that reads as follows (source view):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>Title</key>
        <string> Food</string>
        <key>Rows</key>
        <array>
            <dict>
                <key>name</key>
                <string>Chunky Chips</string>
                <key>price</key>
                <string>25,-</string>
            </dict>
            <dict>
                <key>name</key>
                <string>Chunky Chips w/ Cheese</string>
                <key>price</key>
                <string>29,-</string>
            </dict>
            <dict>
                <key>name</key>
                <string>Fish'n'Chips</string>
                <key>price</key>
                <string>89,-</string>
            </dict>
        </array>
    </dict>
    <dict>
        <key>Title</key>
        <string>Snacks</string>
        <key>Rows</key>
        <array>
            <dict>
                <key>name</key>
                <string>Crisps</string>
                <key>price</key>
                <string>15,-</string>
            </dict>
            <dict>
                <key>name</key>
                <string>Hot Nuts</string>
                <key>price</key>
                <string>20,-</string>
            </dict>
            <dict>
                <key>name</key>
                <string>Popcorn</string>
                <key>price</key>
                <string>25,-</string>
            </dict>
        </array>
    </dict>
    <dict>
        <key>Title</key>
        <string>Draught Beer</string>
        <key>Rows</key>
        <array>
            <dict>
                <key>name</key>
                <string>The Ale</string>
                <key>price</key>
                <string>47,-</string>
            </dict>
            <dict>
                <key>name</key>
                <string>Carlsberg</string>
                <key>price</key>
                <string>47,-</string>
            </dict>
            <dict>
                <key>name</key>
                <string>Kilkenny</string>
                <key>price</key>
                <string>47,-</string>
            </dict>
        </array>
    </dict>
</array>
</plist>

My TableViewController:

#import "MenuViewController.h"

@interface MenuViewController ()

@property (copy, nonatomic) NSArray* tableData;

@end

@implementation MenuViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.tableData = [NSArray arrayWithContentsOfFile: [[NSBundle mainBundle] pathForResource: @"TestList" ofType: @"plist"]];
    NSLog(@"%@",_tableData);

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:(BOOL)animated];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    //return [[[_tableData objectAtIndex: section] objectForKey: @"Rows"] count];
    NSDictionary *dataInSection = [[_tableData objectAtIndex: section] objectForKey: @"Rows"];
    return [dataInSection count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

    return [[_tableData objectAtIndex: section] objectForKey: @"Title"];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"MenuCell";
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    cell.textLabel.text = [[[_tableData objectAtIndex: indexPath.section] objectForKey: @"name"] objectAtIndex: indexPath.row];
    cell.detailTextLabel.text = [[[_tableData objectAtIndex:indexPath.section] objectForKey:@"price"]objectAtIndex: indexPath.row];

    return cell;
}

I would like to show the table with sections. Sectionheaders do show up, but theres no content. I get the following from nslog:

(
        {
        Rows =         (
                        {
                name = "Chunky Chips";
                price = "25,-";
            },
                        {
                name = "Chunky Chips w/ Cheese";
                price = "29,-";
            },
                        {
                name = "Fish'n'Chips";
                price = "89,-";
            }
        );
        Title = " Food";
    },
        {
        Rows =         (
                        {
                name = Crisps;
                price = "15,-";
            },
                        {
                name = "Hot Nuts";
                price = "20,-";
            },
                        {
                name = Popcorn;
                price = "25,-";
            }
        );
        Title = Snacks;
    },
        {
        Rows =         (
                        {
                name = "The Ale";
                price = "47,-";
            },
                        {
                name = Carlsberg;
                price = "47,-";
            },
                        {
                name = Kilkenny;
                price = "47,-";
            }
        );
        Title = "Draught Beer";
    }
)

Any idea why the tablecells aren't populated with the respective names and prices?

This is a great example of why you should not have such long nested method calls on a single line. Your line:

cell.textLabel.text = [[[_tableData objectAtIndex: indexPath.section] objectForKey: @"name"] objectAtIndex: indexPath.row];

should be:

NSDictionary *sectionData = _tableData[indexPath.section];
NSArray *rowsData = sectionData[@"Rows"];
NSDictionary *rowData = rowsData[indexPath.row];
NSString *name = rowData[@"name"];
NSString *price = rowData[@"price"];

cell.textLabel.text = name;
cell.detailTextLabel.text = price;

The way you have it, you forgot to get the data for the Rows key.

Splitting up the lines as I did has a lot of benefits. For each cell there is no reason to have to lookup the section data, rows data, and the row data more than once. So this is much more efficient. Splitting up the code also makes it much easier to debug and also makes it much easier to read.

cell.textLabel.text = [[[_tableData objectAtIndex: indexPath.section] objectForKey: @"name"] objectAtIndex: indexPath.row];
cell.detailTextLabel.text = [[[_tableData objectAtIndex:indexPath.section] objectForKey:@"price"]objectAtIndex: indexPath.row];

Should be (took the liberty to use literals)

cell.textLabel.text = _tableData[indexPath.section][@"Rows"][indexPath.row]@"name"];
cell.detailTextLabel.text = _tableData[indexPath.section][@"Rows"][indexPath.row][@"price"];

You missed referencing the key called "Rows". Here's a possible solution:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"MenuCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    }

    NSDictionary *product = [[[_tableData objectAtIndex:indexPath.section] objectForKey:@"Rows"] objectAtIndex:indexPath.row];
    cell.textLabel.text = [product objectForKey:@"name"];
    cell.detailTextLabel.text = [product objectForKey:@"price"];

    return cell;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM