我一直在做一个用plist填充表格的导航堆栈。但是,当我单击“城市”时,我似乎可以将“名称”信息传递给我的第三个表,因为没有显示任何内容。我确实得到了一个新的弹出表,但它应该填充“大峡谷”,但事实并非如此。我已成功从“目的地”传递到“城市”但不是“名称”。我认为问题在于开始循环不能识别写入“名称”的键。
plist中:
<?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>Destination</key>
<string>Arizona</string>
<key>Tours</key>
<array>
<dict>
<key>City</key>
<string>Phoenix</string>
<key>Options</key>
<array>
<dict>
<key>Name</key>
<string>Grand Canyon</string>
</dict>
</array>
</dict>
</array>
</dict>
<dict>
<key>Destination</key>
<string>California</string>
<key>Tours</key>
<array>
<dict>
<key>City</key>
<string>San Diego</string>
</dict>
<dict>
<key>City</key>
<string>Calexico</string>
</dict>
</array>
</dict>
</array>
</plist>
代码:
#import "OptionsViewController.h"
@interface OptionsViewController ()
@property NSArray *options;
@end
@implementation OptionsViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = @"Available Tours";
// 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)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
-(void)setToursAvailable:(NSString *)toursAvailable{
if (_toursAvailable != toursAvailable) {
_toursAvailable = toursAvailable;
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"Destination" ofType:@"plist"];
NSArray *tours =[NSArray arrayWithContentsOfFile:filePath];
for (int i = 0; i < [tours count]; i++) {
NSDictionary *tourDictionary = [tours objectAtIndex:i];
NSString *tempTour = [tourDictionary objectForKey:@"City"];
if ([tempTour isEqualToString:_toursAvailable]) {
self.options = [tourDictionary objectForKey:@"Options"];
}
}
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.options count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//Fetch Options
NSDictionary *opt = [self.options objectAtIndex:[indexPath row]];
// Configure the cell...
[cell.textLabel setText:[opt objectForKey:@"Name"]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
答案 0 :(得分:6)
上面是Xcode中显示的plist结构,让我帮你调试你的代码。
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"Destination" ofType:@"plist"];
NSArray *tours =[NSArray arrayWithContentsOfFile:filePath];
上面的代码会将巡视中的所有数据加载为数组,即它将包含项目0,项目1等等,让我们看看你的循环,
for (int i = 0; i < [tours count]; i++) {
NSDictionary *tourDictionary = [tours objectAtIndex:i];
}
现在,tourDictionary是字典,它包含2个对象Destination(这是NSString)和Tours(这是NSArray),所以现在要从Tours中获取你的选项
NSArray *allTours = [tourDictionary objectForKey:@"Tours"];
现在,您必须再次遍历该数组,找到您正在寻找的确切城市选项,
即。
for(NSDictionary *allCities in allTours){
if([[allCities objectForKey:@"City"] isEqualToString:_toursAvailable]){
self.options = [allCities objectForKey:@"Options"];
break; //You got your options so just exit this loop.
}
}
所以你的最终代码就像,
for (int i = 0; i < [tours count]; i++) {
NSDictionary *tourDictionary = [tours objectAtIndex:i];
NSArray *allTours = [tourDictionary objectForKey:@"Tours"];
for(NSDictionary *allCities in allTours){
if([[allCities objectForKey:@"City"] isEqualToString:_toursAvailable]){ //Assuming _toursAvailable is City
self.options = [allCities objectForKey:@"Options"];
break; //You got your options so just exit this loop.
}
}
}
答案 1 :(得分:5)
此代码可疑:
for (int i = 0; i < [tours count]; i++) {
NSDictionary *tourDictionary = [tours objectAtIndex:i];
NSString *tempTour = [tourDictionary objectForKey:@"City"];
if ([tempTour isEqualToString:_toursAvailable]) {
self.options = [tourDictionary objectForKey:@"Options"];
}
}
我认为错误是@"City"
不是外部字典中的关键字。
你可以尝试:
NSString *path = [[NSBundle mainBundle] pathForResource:@"Destination" ofType:@"plist"];
NSArray *destinations = [NSArray arrayWithContentsOfFile:path];
[destinations enumerateObjectsUsingBlock:^(id destObj, NSUInteger idx, BOOL *stop) {
NSUInteger index = [destObj[@"Tours"] indexOfObjectPassingTest:^BOOL(id tourObj, NSUInteger idx, BOOL *stop) {
return [tourObj[@"City"] isEqualToString:_toursAvailable];
}];
if( index != NSNotFound ) {
self.options = destObj[@"Tours"][index][@"Options"];
*stop = YES;
}
}];
看起来该堆栈中的先前UITableViewController
必须设置为toursAvailable
,尽管我们没有看到该代码或OptionsViewController
类接口。如果是这种情况,那么你需要确定它是否正确设置。
既然您确实表示感谢任何帮助,我提出了一个与切线相关的建议:
使用正确的对象图来表示您的模型。您正在使用目的地,旅游,城市等。为什么不在您的应用程序模型中代表那些?当然,在这个阶段,你只是用一个plist的代码播种你的应用程序;但是,如果您想通过Web API下载游览,或者允许用户对游览或其他任何内容发表评论,会发生什么。 plist-as-model-layer方法使这很困难。其他人也难以获取代码并阅读它。通过显式的对象类比使用包含字典等的数组的字典数组更容易处理对象关系。