我正在使用一个 Web 服务,它从我服务器上的数据库返回一个 JSON 格式的数据,这些数据将显示在我的 iPhone 应用程序的某个 View 中。
由于该应用程序是免费的,所以我在我的数据库中获得了数千行,当然我必须下载 JSON 数据。
如何对我的 JSON 数据进行延迟加载?请任何代码行将不胜感激。
谢谢。
编辑 1:
换句话说,我正在使用 Sql 请求,例如“从表中选择所有内容”,然后将此数据作为 JSON 返回到我的应用程序。
我怎样才能请求一个小数字然后添加其他人等..?
最佳答案
术语“延迟加载”可能并不完全适合单个 JSON 响应,它可能使我们倾向于采用一种方法而不是另一种方法。因此,让我解决我认为的潜在问题,即尽管服务器数据库非常大,但您仍希望获得改进的用户体验:
NSXMLParser
在解析进行之前,实现尝试一次将整个 XML 提要(或尽可能多地?)加载到内存中(尽管方法名称会暗示相反)。如果您的应用使用了 LibXML2
(例如在 Apple 的 AdvancedURLConnections sample 中),您可以在向用户呈现初始数据的同时继续在后台下载和解析 XML。这将同时产生大多数人与“延迟加载”(即在将结果呈现给用户之前不等待所有内容)和“急切加载”(即它将下载下一条记录,以便它们当他们去那里时已经为用户准备好了)。 为了让我们提出更明智的建议,您确实需要分享更多关于 JSON 的性质及其背后数据的信息,描述为什么您认为“延迟加载”是解决方案等。您可能不想在特定的解决方案,直到您对数据进行一些分析(例如,数千行的 JSON 仍然可以小于单个大图像)。
更新:
如果您打算采用第一种方法,您首先需要更改您的 Web 服务,以便响应请求,它只提供 n 条记录,从特定的记录号开始。您可能还需要返回服务器上的总记录数,以便您可以向用户提供一些关于要滚动多少的视觉提示。
其次,您需要更新您的 iOS 应用程序以支持此模型。因此,在您的 UI 中,当您滚动浏览结果时,您可能希望您的用户界面通过显示 (a) 实际结果(如果您已经获取它)来响应滚动事件;或 (b) 一些 UI,它在视觉上指示正在检索相关记录,然后从服务器异步请求信息。如果您在
UITableViewCell
中执行此操作,它可能会执行以下操作:- (void)viewDidLoad
{
[super viewDidLoad];
[self initiateRequestForFirstSetOfData];
}
- (void)initiateRequestForFirstSetOfData
{
// asynchronously retrieve the data from the server:
// (a) retrieve the total number of records
// (b) retrieve the actual data for the first n records
// and when this is done, dispatch a `[self.tableView reloadData]` back to the
// main queue.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.totalNumberOfRecordsOnServer;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
BOOL isAvailable = ... // do whatever logic to determine if this row has already been retrieved
if (isAvailable)
{
// configure the cell like normal here
}
else
{
// configure the cell to indicate that a fetch is in progress here.
// perhaps add a UIActivityIndicatorView and startAnimating it
dispatch_async(backgroundQueue, ^{
// initiate the request for the data (if you haven't already)
dispatch_async(dispatch_get_main_queue(), ^{
// don't just update the UI here, but make sure the cell
// in question is still on screen by calling `UITableView`
// method `cellForRowAtIndexPath`, not to be confused with
// this method, which is a `UITableViewController` method.
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell)
{
// update the cell: sometimes you can get away with
// updating the cell directly, sometimes you want to
// just call something like:
//
// [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
});
});
}
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
return cell;
}
我可能会建议对上面的代码进行大量改进,相当简单的代码,但希望它能为您提供基本的想法。你 (a) 算出总共有多少行数据; (b) 您检索前 n 条记录; (c) 当用户滚动到一条记录时,如果你有它,你就显示它,但如果没有,提供视觉提示,你将异步地为他们获取该数据; (d) 当数据进入时,如果合适,更新 UI。
就像我说的那样,我可能会对上述代码进行一些改进,例如,我可能不会将异步检索嵌入到 View Controller 本身中,而是在我的模型中执行此操作并使用一些委托(delegate)模式来更新 UI,我可能会使用操作队列而不是调度队列,这样我就可以取消我们不再需要的请求,等等,但你明白了基本的想法。
如果您使用的是
UICollectionViewController
,类似于上面的代码。如果您使用 ScrollView ,模式非常相似,尽管您会响应 UIScrollViewDelegate
方法 scrollViewDidScroll
取而代之(您不仅需要像上面那样编写代码,还需要编写一些可以释放 UIKit
已滚出屏幕的元素的代码)。
关于ios - 如何实现延迟json文件下载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13980386/