reloadData没有被立即调用(NSXMLParserDelegate困境)

时间:2012-10-11 03:48:04

标签: ios uitableview nsxmlparser reloaddata

我继承了一些我试图调试的血腥可怕的代码。

我正在使用NSXMLParser解析RSS提要。在解析器:didEndElement:etc:中,当每个新项出现时,我触发另一个调用UITableView的reloadData方法的方法。但是,调用它们时不调用reloadData方法,但稍后...在parserDidEndDocument之后调用:...然后它们全部触发。

似乎reloadData请求在某处排队,在解析线程上阻塞。

当我告诉它时,如何强制reloadData触发,而不是在它想要的时候触发。我的问题是,因为它只在所有新闻项目加载后重新加载 - 并且有很多新闻项目 - UI体验不是最理想的。

1 个答案:

答案 0 :(得分:2)

您的推测是正确的。仅当程序控制返回主运行循环时才会更新用户界面。然而,NSXMLParser完全同步工作:parse方法解析整个XML数据(调用委托函数等)并仅在解析完成时返回。因此,在reloadData中呼叫parser:didEndElement:...没有立即显示效果。

如果解析XML数据确实需要花费很多时间而不能在reloadData方法返回时调用parse,则必须将解析操作移到单独的线程中:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [myParser parse];
});

dispatch_async立即返回,并在后台线程上完成解析。 因此,委托方法也在后台线程上调用。由于UI的更新只能在主线程上完成,因此您可以按如下方式进行操作 parser:didEndElement:...

YourType newObject = ... // create new object from XML data
dispatch_async(dispatch_get_main_queue(), ^{
    // assuming that self.dataArray is your data source array for the table view 
    int newRow = [self.dataArray count]; // row number for new object
    [self.dataArray addObject:newObject]; // add to your data source
    // insert row in table view:
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:newRow inSection:0];
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                          withRowAnimation:UITableViewRowAnimationAutomatic];
});

使用insertRowsAtIndexPaths代替reloadData可以提供更顺畅的"用动画更新UI。

我希望我的示例代码中没有太多的语法错误,这会有所帮助。否则随便问。