我正在开发一个iPhone应用程序,它使用TableView来显示XML数据。 XML数据来自外部资源并被解析并放入对象中以用作表数据源。该应用程序使用UITabBar和多个ViewControllers,这些都是以编程方式创建的,并使用相同的数据源。刷新XML数据和更新UITableView
一切都很好,但我想实现一个刷新按钮,以便用户可以刷新内容(全局,所以所有的ViewControllers应该更新)。解析器将再次查询XML并创建一个新对象。我遇到的问题是我似乎无法用我的新数据重新填充tableview。我得到更新的数据对象。实际上更新tableview是个问题。我尝试设置setDataSource
并致电reloadData
,但由于无法识别的选择器导致崩溃。
从我的AppDelegate调用XML的东西,所有的解析逻辑都在Parser.m中。刷新函数被调用RootViewController.m,它实现了UITableViewDataSource协议:
- (void)refreshXMLFeed:(id)sender {
NSArray *tableControllersData = [appDelegate getData];
[self.tableView setDataSource: tableControllersData];
[self.tableView reloadData];
}
我将如何处理这一问题?应该获取新数据并重新加载RootViewController中的表视图,正如我一直试图完成的那样。或者应该在AppDelegate中触发数据解析,并且只需要重新加载RootViewController中的TableView。
如果有必要,我可以用必要的代码更新我的问题,我不确定哪一部分在这一点上是相关的。
RootViewController.h:
#import <UIKit/UIKit.h>
@interface RootViewController : UITableViewController {
MyAppDelegate *appDelegate;
NSArray *tableDataArray;
}
@property (nonatomic, retain) NSArray *tableDataArray;
- (IBAction)refreshXMLFeed:(id)sender;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil tableDataSource:(NSArray*)tableData;
@end
RootViewController.m:
#import "CustomCell.h"
#import "MyAppDelegate.h"
#import "RootViewController.h"
#import "DetailViewController.h"
@implementation RootViewController
@synthesize tableDataArray;
- (void)viewDidLoad {
[super viewDidLoad];
}
//Override the default initWithNibName method
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil tableDataSource:(NSArray*)tableData {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
tableDataArray = [tableData retain];
}
return self;
}
-(void)viewWillAppear:(BOOL)animated {
appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
[super viewWillAppear:animated];
//Set the colour of the navigationController and add buttons
self.navigationController.navigationBar.tintColor = [UIColor blackColor];
//Add the refresh button
UIBarButtonItem* refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshXMLFeed:)];
[self.navigationItem setLeftBarButtonItem:refreshButton animated:YES];
[refreshButton release];
}
#pragma mark Table
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.tableDataArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CustomCellIdentifier = @"CustomCellIdentifier";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];
if (cell == nil) {
NSArray *cellNib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
for (id oneObject in cellNib) {
if ([oneObject isKindOfClass:[CustomCell class]]) {
cell = (CustomCell *)oneObject;
}
}
}
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.tableDataArray objectAtIndex:row];
cell.colorLabel.text = [rowData objectForKey:@"Type"];
cell.nameLabel.text = [rowData objectForKey:@"Name"];
UIImage *image = [UIImage imageNamed:[rowData objectForKey:@"Icon"]];
cell.image = image;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *selectedRow = [tableDataArray objectAtIndex:indexPath.row];
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailView" bundle:[NSBundle mainBundle]];
detailViewController. selectedRow = selectedRow;
[self.navigationController pushViewController:detailViewController animated:YES];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] init];
backButton.title = @"Back";
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
[detailViewController release];
detailViewController = nil;
}
#pragma mark Refresh
- (void)refreshXMLFeed:(id)sender {
NSArray *tableControllersData = [appDelegate getData];
[self.tableView setDataSource: tableControllersData];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
@end
感谢您的回复。所需的方法都在RootViewController中实现 - 我用代码更新了最初的问题。 dataSource的数据是一个NSArray,并通过重写的
initWithNibName
方法提供。所以我不确定这是否与未实现的方法有关。 – mensch 2009-12-15 09:17:39表视图的数据源*不能是NSArray,因为NSArray没有实现UITableViewDataSource协议。如果您在RootViewController中实现了所需的方法,那么将RootViewController实例(或者如果它位于RootViewController内部的self)设置为表视图的数据源。你的问题与initWithNibName无关。问题是你不了解MVC。数据源是一个委托 - 而不是数据容器。委托人应该访问数据容器(在你的情况下是一个NSArray),以便返回正确的行/段数和表格单元格。 – 2009-12-15 19:27:45
对不起,混淆了术语,NSArray的确是数据容器而不是dataSource(它是数据源,但是,因此混合)。 RootViewController实现了UITableViewDataSource协议的方法,并且是TableView的正确数据源。我猜我在这种情况下的问题是如何提供更新的数据容器NSArray并相应地更新TableView。 – mensch 2009-12-15 23:01:59