我正在開發一個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