【问题标题】:How to separate UITableView from data parsed from the Internet?如何将 UITableView 与从互联网上解析的数据分离?
【发布时间】:2012-07-31 19:52:13
【问题描述】:
我有一个UITableView,其中填充了来自 Internet 的已解析 XML 元素。
一切正常,但我想将解析 XLM 元素的代码与负责填充此 UITableView 的 UIViewController 分开。
我尝试过对UIViewController 进行子类化,但这似乎会导致许多耦合问题。
分离此 XML 异步解析器代码,然后将其结果提供给包含 UITableView 的 UIViewController 的最佳方法是什么?
我不太了解代表,但这是要走的路吗?
谢谢!
【问题讨论】:
标签:
iphone
cocoa-touch
uitableview
uiviewcontroller
xml-parsing
【解决方案1】:
编写一个处理解析的对象,在视图控制器中创建它的一个实例,然后调用它来加载数据:
@protocol SomeXMLParserHandler <NSObject>
- (void) handleData:(NSArray *)data;
@end
@interface SomeXMLParser : NSObject<NSXMLParserDelegate>
@property (strong, nonatomic) id<SomeXMLParserHandler> handler;
- (void) parseSomeXMLFromURL:(NSString *)url
andPassToHandler:(id<SomeXMLParserHandler>)handler;
@end
在此示例中,SomeXMLParser 将完成所有繁重的工作,并在完成后将数组传回 SomeXMLParserHandler。因此,在您的视图控制器中,您可以执行类似的操作:
- (void) viewDidLoad
{
[super viewDidLoad];
SomeXMLParser *parser = [[SomeXMLParser alloc] init];
[parser parseSomeXMLFromURL:@"http://someurl"
andPassToHandler:self];
}
- (void) handleData:(NSArray *)data
{
self.tableViewData = data;
}
这不是工作代码,但它应该让你朝着正确的方向前进,特别是如果你已经让解析代码工作了。此外,如果您进入 Blocks...,您可以在解析完成后将协议替换为 Block 引用来完成工作。
【解决方案2】:
您的模型应该处理数据的获取和解析,然后当它完成后,您可以使用 NSNotificationCenter 通知您的视图控制器有关新数据的信息。
例如,您可以执行以下操作:
在您的模型中定义一些 MyModelDidFinishFetchingDataNotification 并在您完成获取和解析数据时调用它
然后当你创建你的 viewController 时,将它作为观察者添加到你的模型通知中
- (id)init
{
self = [super init];
if (self) {
//
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleMyModelDidFinishFetchingDataNotification:)
name:MyModelDidFinishFetchingDataNotification
object:nil];
}
return self;
}
在 viewDidLoad 中告诉你的模型去获取数据
- (void)viewDidLoad
{
[super viewDidLoad];
[self.myModel fetchNewDataFromServer];
}
实现处理新数据的方法
- (void)handleMyModelDidFinishFetchingDataNotification:(NSNotification *)not
{
NSArray *newData = [[not userInfo] objectForKey:@"someNewData"];
// set the new data to the viewController data property
self.myData = newData
// update the UI
[self.tableView reloadData];
}