刷新XML数据并更新UITableView [英] Refreshing XML data and updating a UITableView

查看:67
本文介绍了刷新XML数据并更新UITableView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个iPhone应用程序,该应用程序使用TableView来显示XML数据. XML数据来自外部资源,经过解析后放入对象中,以用作表数据源.该应用程序使用一个UITabBar和所有以编程方式创建并使用相同数据源的多个ViewController.

I'm developing an iPhone application which uses a TableView to display XML data. The XML data comes from an external resource and is parsed and put into an object for use as a table dataSource. The application uses a UITabBar and multiple ViewControllers all programmatically created and using the same dataSource.

一切都很好,但我想实现一个刷新按钮,以便用户可以刷新内容(全局刷新,因此应更新所有ViewController).解析器将再次查询XML并创建一个新对象.我遇到的问题是我似乎无法用新数据重新填充tableview.我得到了更新的数据对象.实际上,实际上更新tableview是一个问题.我尝试设置setDataSource并调用reloadData,但是由于选择器无法识别,这会导致崩溃.

Everything is fine and dandy, but I'd like to implement a refresh button, so that a user can refresh the content (globally, so all the ViewControllers should be updated). The parser will query the XML again and create a new object. The problem I'm having is that I can't seem to repopulate the tableview with my new data. I get the updated data object. Actually updating the tableview is a problem though. I've tried to set setDataSource and call reloadData, but this results in a crash due to an unrecognised selector.

从我的AppDelegate调用XML内容,所有解析逻辑都在Parser.m中.在RootViewController.m中调用刷新函数,该函数实现了UITableViewDataSource协议:

The XML stuff is called from my AppDelegate and all the parsing logic is in Parser.m. The refresh function is called in RootViewController.m, which implements the UITableViewDataSource protocol:

- (void)refreshXMLFeed:(id)sender {
  NSArray *tableControllersData = [appDelegate getData];
  [self.tableView setDataSource: tableControllersData];
  [self.tableView reloadData];  
}

我将如何处理此问题?我应该尝试获取新数据并在RootViewController中重新加载表视图.还是应该在AppDelegate中触发数据解析,而仅在RootViewController中重新加载TableView.

How would I approach this issue? Should get the new data and reload the table view in the RootViewController as I have been trying to accomplish. Or should the data parsing be triggered in the AppDelegate and only the reloading of the TableView in RootViewController.

如果有必要,我可以用必要的代码更新问题,但现在不确定哪些部分是相关的.

If necessary I can update my question with the necessary code, I'm not sure which parts are relevant at this point.

RootViewController.h:

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:

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

推荐答案

您应该只设置一次数据源,而不应该是NSArray.从中提取记录的数据容器可以更改,但是数据源应始终相同.在大多数情况下,数据源应该只是您的视图控制器.然后,您的视图控制器应在

You should only be setting your data source once and it should not be an NSArray. The data container from which you pull your records can change, but the data source should always be the same. In most cases the data source should just be your view controller. Then your view controller should implement the methods in the UITableViewDataSource protocol including:

– tableView:cellForRowAtIndexPath:  required method
– numberOfSectionsInTableView:
– tableView:numberOfRowsInSection:  required method
– sectionIndexTitlesForTableView:
– tableView:sectionForSectionIndexTitle:atIndex:
– tableView:titleForHeaderInSection:
– tableView:titleForFooterInSection:

NSArray不响应这些方法中的任何一个,这就是为什么您收到无法识别的选择器消息的原因.您必须自己实现它们.

An NSArray doesn't respond to any of these methods which is why you are getting the unrecognized selector message. You have to implement them yourself.

您应该熟悉

You should familiarize yourself with the Table View Programming Guide to understand how to effectively use table views.

最诚挚的问候.

更新:以下一些代码可能会对您有所帮助.在您的RootViewController中,使用-viewDidLoad中的alloc/init实例化NSArray.称它为物品:

UPDATE: Here's a little code that might help you. In your RootViewController instantiate the NSArray with alloc/init in the -viewDidLoad. Call it items:

- (void)viewDidLoad;
{
    [super viewDidLoad];
    items = [[NSArray alloc] init];
}

然后实现表视图的数据源委托,如下所示:

Then implement your table view's data source delegates like this:

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
    return [items count];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
{
    return 1;
}

然后您需要实现cellForRowAtIndexPath:

Then you need to implement your cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;

    cell = [tv dequeueReusableCellWithIdentifier:@"Cell"];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"] autorelease];

    }

    // Get your item from the items array here
    NSDictionary *item = [items objectAtIndex:[indexPath row]];
    NSString *text = [item valueForKey:@"text"];

    [[cell textLabel] setText:text];

    return cell;

}

此代码假定您NSArray中的对象是NSDictionaries.如果您使用的是自定义对象,则将该对象的索引路径转换为自定义类型,然后使用其字段.

This code assumes that the objects in your NSArray are NSDictionaries. If you are using some custom object, cast the object at that index path to your custom type and then use it's fields.

当有新数据可用并需要重新加载表视图时,您只需重新分配项NSArray,然后在表视图上调用reloadData.假设您发生了这样的重新加载:

When you have new data available and need to reload your table view, you will simply re-allocate your items NSArray and then call reloadData on the tableview. Say you have a reload occurring like this:

- (void)didReciveNewData:(NSArray*)newItems;
{
    if (items) [items release], items = nil;
    items = [newItems copy];
    [tableView reloadData];
}

这将导致表视图向其视图控制器查询要显示的行数以及每行的单元格,这是通过访问NSArray的计数和内容而提供的.

This will cause the table view to query its view controller for the number of rows to display and the cells for each row again which are provided by accessing the count and contents of the NSArray.

HTH.

这篇关于刷新XML数据并更新UITableView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆