开发者

Accessing data from an Array of dicionaries containing an array

开发者 https://www.devze.com 2023-01-08 17:01 出处:网络
I\'m a bit stumped and I\'m hoping someone can help me. I\'ve got a plist which is an array of dictionaries. I\'m trying to read it into a table. The plist looks like this:

I'm a bit stumped and I'm hoping someone can help me. I've got a plist which is an array of dictionaries. I'm trying to read it into a table. The plist looks like this:

<array>
    <dict>
        <key>sectionTitle</key>
        <string>A</string>
        <key>rowData</key>
        <array>
            <dict>
                <key>Title</key>
                <string>Albert Author</string>
                <key>dText</key>
                <string>text for detail view</string>
            </dict>
            <dict>
                <key>Title</key>
                <string>Antony Author</string>
                <key>dText</key>
                <string>Descriptive text for detail view</string>
            </dict>
            <dict>
                <key>Title</key>
                <string>Azerifiel Author</string>
                <key>dText</key>
   开发者_如何转开发             <string>Text for detail view</string>
            </dict>
        </array>
    </dict>
    <dict>
        <key>sectionTitle</key>
        <string>B</string>
        <key>rowData</key>
        <array>
            <dict>
                <key>Title</key>
                <string>Barny Author</string>
                <key>dText</key>
                <string>text for detail view</string>
            </dict>
            <dict>
                <key>Title</key>
                <string>Bazle Author</string>
                <key>dText</key>
                <string>text for detail view</string>
            </dict>
            <dict>
                <key>Title</key>
                <string>Bruno Author</string>
                <key>dText</key>
                <string>text for detail view</string>
            </dict>
        </array>
    </dict>
</array>

My problem is this: I can make a similar structure minus the Arrays populate a table view, but I can't make the above code with the arrays work. I'm not sure how to deal with the arrays in the code, yet I can't get rid of them because I want the final table to be indexed and sectioned. Here's the code from my viewDidLoad method.

- (void)viewDidLoad {
    [super viewDidLoad];

    // Path to the plist (in the application bundle)
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Tester" ofType:@"plist"];

    // Build the array from the plist  
    NSArray *dictArray = [[NSArray alloc] initWithContentsOfFile:path];
    NSMutableArray *mutableArray = [[NSMutableArray alloc] init];

    for(NSDictionary *dict in dictArray)
    {
        DictModel *term = [[DictModel alloc] init];
        term.sectionTitle = [dict objectForKey:@"sectionTitle"];
        term.Title = [dict objectForKey:@"Title"];
        term.dText = [dict objectForKey:@"dText"];
        [mutableArray addObject:term];
        [term release];
    }

    tableDataSource = [[NSArray alloc] initWithArray:mutableArray];
    [mutableArray release];
    [dictArray release];
    [super viewDidLoad];
}

I've got a separate class called DictModel which looks like this:

@interface DictModel : NSObject {
    NSString *sectionTitle;
    NSString *Title;
    NSString *dText;
}

@property(nonatomic, retain) NSString *sectionTitle;
@property(nonatomic,retain) NSString *Title;
@property(nonatomic, retain) NSString *dText;

@end

Where am I going wrong? I tried importing the Arrays but couldn't get it to work. I Figure I'm misunderstanding something somewhere. Advice is much appreciated.

Here's my cell for row method. This might be where the display problem is. I've added this at the request of a comentator:

- (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];
}

// Configure the cell.
DictModel *term = [tableDataSource objectAtIndex:indexPath.row];
cell.textLabel.text = term.Title;
cell.detailTextLabel.text = term.dText;

return cell;

}


I solved this problem a little while ago with a bit of help from the good people on here and in the mac Dev forums. I thought I'd come back and share what I learned for anyone else who is new to iphone Dev (like me) and struggling with this problem.

PLEASE NOTE: The following is written to the best of my understanding of what I've learned trying to solve this problem, so there may be a few technical errors in my description. If you spot any, I'd be glad if you'd point them out. I'm engaged in iphone development because I want to learn to program, so corrections welcome!

First off My Plist still looks the same. It's an Array of Dictionaries. This really is a much simpler way of doing what I wanted to do than using a Dictionary of Arrays which is what I initially started with. The reason the code in my original posting looks so bad is because it was based on my understanding of how to populate a table using a Dictionary of Arrays, which is clunky.

Data source dealt with, let's move onto my .h file. it's pretty simple and looks like this:

@interface MyTableViewController : UITableViewController 
{
IBOutlet UITableView *myTableView;
MyDetailViewController *myDetailViewController;
NSArray *tableDataSource;

}

@property (nonatomic, retain) myDetailViewController *myDetailViewController;
@property (nonatomic, retain) NSArray *tableDataSource;

@end

All pretty self evident. I've got my outlet for my table view and my detail table view. I've also got an array that I will read my .plist through into the table.

Moving onto my .m file which looks like this:

@implementation TableViewController
@synthesize myDetailViewController;
@synthesize tableDataSource; 

- (void)viewDidLoad {
[super viewDidLoad];

self.title = NSLocalizedString(@"Tester", @"Browse by name");

// Path to the plist (in the application bundle)
NSString *path = [[NSBundle mainBundle] pathForResource:@"Testers" ofType:@"plist"];

// Retrieve the plist's root element array  
NSArray *array = [[NSArray alloc] initWithContentsOfFile:path];

// Assign the plist array to my instance variable
self.tableDataSource = array;
[array release];
} 

Bearing my original question in mind, I guess the important part to concentrate on is the viewDidLoad method. Basically, after the super I assign the name to the top of the table view. I then create a string called 'path' that is made up out of my .plist called "Testers". I create an array called 'array' and initialise it with the contents of the string I previously just made called 'path'. Finally I assign my .plist array to my NSArray instance variable 'tableDataSource'. This is so much more simple than my original attempt. For one thing I don't need the separate class model any more.

The next key thing is my cellForRowAtIndexPathMethod which now looks like this:

- (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];
}

// Configure the cell.
NSDictionary *sectionDictionary = [tableDataSource objectAtIndex:indexPath.section];
NSArray *sectionRowArray = [sectionDictionary objectForKey:@"rowData"];
NSDictionary *rowDictionary = [sectionRowArray objectAtIndex:indexPath.row];
cell.textLabel.text = [rowDictionary objectForKey:@"Title"];
return cell;
}

This is almost the same as before except the means by which the cell is configured has altered to accommodate my new way of reading data from the .plist. So I'm no longer referring to Dict model. "rowData" and "Title" are keys in my plist (see very top of page). "rowData" is the key for each section and "Title" is the text that is visible in the cell when the script is running.

The other key bit of info is the didSelectRowAtIndexPath Method, which determines what is pushed into the detail view when a cell is selected. It looks like this:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Get the dictionary of the selected data source.
NSDictionary *dictionary = [[[self.tableDataSource objectAtIndex:indexPath.section]objectForKey:@"rowData"] objectAtIndex:indexPath.row];

MyDetailViewController *controller = [[MYDetailViewController alloc] initWithNibName:@"MyDetailView" bundle:[NSBundle mainBundle]]; 

controller.title = [dictionary objectForKey:@"Title"];
controller.dText = [dictionary objectForKey:@"dText"];

[self.navigationController pushViewController:controller animated:YES];

[controller release];

}

I begin by getting the dictionary for the table data source which was assigned to my instance variable 'tableDataSource' in my viewDidLoad method. I then tell my view detail controller it's nib in the mainbundle and tell it that when the detail view is pushed it should put whatever is in the position of the key "Title" as the title of that particular instance of the detail view and that it should populate the TextView in that nib with the text in the .plist at the key "dText".

Well, that's about it. It worked fine for me, though I can't swear it's the correct way of doing it. Thanks to the people who helped me get it in the end, I've climbed another mole hill!

Hope this is of use to someone else.

0

精彩评论

暂无评论...
验证码 换一张
取 消