Objective-C iOS:立即从JSON Stream开始填充UITableView



我有一个带有单元格的UITableView,用于显示来自庞大(5000 个项目)JSON 文件的图像和文本。我想流式传输 JSON 并立即开始更新UITableView,但似乎无法为此解决管道问题。

- (NSArray *)parseJSONIntoImageObjectsFromData:(NSData *)rawJSONData {
  NSError *error;
  NSMutableArray *arrayOfImageObjects = [[NSMutableArray alloc] init];
  NSURL *myURL = [[NSURL alloc] initWithString:self.urlString];
  NSData *objects = [NSData dataWithContentsOfURL:myURL];
  NSInputStream *stream = [[NSInputStream alloc] initWithData:objects];
  [stream open];
  NSMutableArray *arrayFromStream = [NSJSONSerialization JSONObjectWithStream:stream options:NSJSONReadingAllowFragments error:&error];
  for (NSDictionary *JSonDictionary in arrayFromStream) {
    NSLog(@"Count is %lu", (unsigned long)arrayOfImageObjects.count);
    NSInteger imgID = (NSInteger)JSonDictionary[@"id"];
    ImageObject *newImageObject = [[ImageObject alloc] initWithID:imgID andTitle:JSonDictionary[@"title"] andThumbnailURL:JSonDictionary[@"thumbnailUrl"]];
    [arrayOfImageObjects addObject:newImageObject];
  }
  return arrayOfImageObjects;
}

这肯定会将它们作为流获取,正如调试窗口中NSLog显示的那样。但由于它等待返回,它必须完成。我对这样做有点困惑,找不到一个好的代码示例。我可能会返回流吗?

编辑:我并不是非常担心我遇到的短暂延迟,我确信延迟更多的是检索而不是解析,我只是想学习将数据作为流检索并增量更新UITableView作为一种方式做得更好。我喜欢从事数据检索和操作工作,并试图通过了解更多来提高我的技能。

此外,图像是在显示时使用NSOperationQueue异步检索的,对于此任务并不重要。

如果你对此

进行基准测试,我想你会发现 JSON 的解析时间是无关紧要的。缓慢的部分将是原始JSON的下载(以及可能的ImageObject对象的创建)。您应该在仪器中对此进行基准测试(使用"时间分析器"工具)并使用"记录等待线程"选项。请参阅 WWDC 视频 在 iOS 上构建并发用户界面 有关如何使用 Instruments 诊断此类问题的演示。

我会首先停用dataWithContentsOfURL,因为它是同步运行的。我建议使用异步技术,例如NSURLSession方法dataWithURL(或者如果您需要对iOS 7之前的支持,NSURLConnection方法sendAsynchronousRequest)。

通常,在这些情况下,JSON 足够小,最大的延迟源于发出初始请求的网络延迟。我提到这一点是为了让您不必在没有确认这将解决问题的情况下开始对分页/流方法的代码进行一些重大重构。

此外,您尚未共享此ImageObject逻辑,但如果这是同步加载图像,则也可能是重构异步检索的候选者。如果不了解有关该类的更多信息,则很难在这一点上为您提供进一步的建议。

NSMutableArray *arrayOfImageObjects定义为此方法之外的属性或变量,然后在 for 循环中,在可能每 100 个对象之后调用 [self.tableView reloadData]。

这是假设您的 numberOfRowsInSection 也关闭了 arrayOfImageObjects,并且 cellForRowAtIndexPath 正在使用它来填充表数据。

但也要考虑对数据进行"分页",以便一次只加载 50 个左右的对象(假设您的 API 支持此功能,例如"http://example.com/imagedata?page=1")。然后,如果用户轻拂或滚动表视图,您可以执行另一个 api 调用,增加页码并将该新数据集添加到当前数据集并调用 reloadData。

编辑:我也假设你的"parseJSONIntoImageObjectsFromData"正在异步运行。如果没有,那么使用类似AFNetworking的东西(或sendAsyncRequest:queue:completionHandler:在NSURLConnection中),在完成块中,你可以开始添加到你的数组中。

最新更新