2

我正在使用从服务器上的数据库返回 JSON 格式数据的 Web 服务,这些数据将显示在我的 iPhone 应用程序的某些视图中。

由于该应用程序是免费的,所以我的数据库中有数千行,当然还有我必须下载的 JSON 数据。

如何对我的 JSON 数据进行延迟加载?请任何代码行将不胜感激。

谢谢。

编辑 1:

换句话说,我正在使用诸如“从表中全选”之类的 Sql 请求,然后将此数据作为 JSON 返回到我的应用程序。

我怎样才能请求一个小号码然后添加其他人等..?

4

1 回答 1

3

术语“延迟加载”可能并不完全适合单个 JSON 响应,它可能使我们倾向于一种方法而不是另一种方法。因此,让我来解决我认为的基本问题,即尽管服务器数据库非常大,但您仍希望获得改善的用户体验:

  1. 如果 JSON 真的很大,你总是可以考虑一个“分页”的比喻,你下载前x条记录,然后对服务器数据的下一个“页面”发出后续请求。鉴于可以在请求之间添加额外的服务器记录,您必须仔细考虑该实现,但这可能很容易做到。

  2. 另一种提高 JSON 效率的方法是限制初始请求中返回的数据。例如,第一个请求可能只返回所有或合理的记录子集的标识符或标头信息,然后您可能有后续请求以获取更多详细信息(例如,用户转到详细信息屏幕)。

  3. 如果 JSON 当前包含任何大型数据元素(例如,Base64 编码的二进制数据,如图像或声音文件),则前一点的特定排列将是。通过将这些排除在初始响应之外,这将解决许多问题。如果您可以返回此二进制数据的 URL,而不是数据本身,那肯定会适合延迟加载(以及让您能够轻松下载二进制信息,而不是大 33% 的 Base64 编码) . 如果您正在处理图像,您可能还需要考虑缩略图v 大图像的想法,特别是在延迟加载模型中处理后者。

  4. 您可以考虑实现一个支持流的 XML 解析版本。标准NSXMLParser实现尝试在解析继续之前一次将整个 XML 提要(或尽可能多的?)加载到内存中(尽管方法名称会暗示相反)。如果您的应用使用LibXML2了(例如在 Apple 的AdvancedURLConnections 示例中),您可以在将初始数据呈现给用户的同时继续在后台下载和解析 XML。这将同时产生大多数人与“延迟加载”(即您在将结果呈现给用户之前不会等待所有内容)和“急切加载”(即它将下载下一条记录,因此它们当他们去那里时已经为用户准备好了)。

为了让我们提出更明智的建议,您确实需要分享有关 JSON 的性质及其背后的数据的更多信息,描述为什么您认为“延迟加载”是解决方案等等。您可能不想发疯特定的解决方案,直到您对数据进行一些分析(例如,数千行的 JSON 仍然可以小于单个大图像)。


更新:

如果您打算采用第一种方法,您首先需要更改您的 Web 服务,以便在响应请求时,它只提供从特定记录编号开始的n条记录。您可能还需要返回服务器上的记录总数,以便您可以为用户提供一些视觉提示,以了解有多少需要滚动。

其次,您需要更新您的 iOS 应用程序以支持此模型。因此,在您的 UI 中,当您滚动浏览结果时,您可能希望您的用户界面通过显示(a)实际结果(如果您已经获取它)来响应滚动事件;或 (b) 一些 UI 可以直观地指示正在检索相关记录,然后从服务器异步请求信息。如果您在 a 中执行此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。

就像我说的,我可能会对上面的代码进行一些改进,例如,我可能不会在视图控制器本身中嵌入异步检索,而是在我的模型中这样做并有一些委托模式来更新 UI,我'可能会使用操作队列而不是调度队列,所以我可以取消我们不再需要的请求等,但你明白了基本的想法。

如果你使用 a UICollectionViewController,它类似于上面的代码。如果您使用滚动视图,则模式非常相似,尽管您将改为响应该UIScrollViewDelegate方法scrollViewDidScroll(并且您不仅需要编写代码,还需要编写一些可以释放UIKit已滚动元素的代码也离开屏幕)。

于 2012-12-20T23:18:27.070 回答