Ios 如何实现惰性json文件下载?

Ios 如何实现惰性json文件下载?,ios,json,lazy-evaluation,Ios,Json,Lazy Evaluation,我使用的web服务从服务器上的数据库返回JSON格式的数据,这些数据将显示在iPhone应用程序的某些视图中 因为这个应用程序是免费的,所以我在我的数据库上有数千行,当然还有我必须下载的JSON数据 如何对JSON数据进行延迟加载?请任何代码行将非常感谢 谢谢 编辑1: 换句话说,我使用一个Sql请求,比如“从表中全选”,然后将该数据作为JSON返回给我的应用程序 我如何申请一个小号码,然后添加其他号码等 术语“延迟加载”可能并不完全适用于单个JSON响应,它可能使我们倾向于一种方法而不是另一种

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

因为这个应用程序是免费的,所以我在我的数据库上有数千行,当然还有我必须下载的JSON数据

如何对JSON数据进行延迟加载?请任何代码行将非常感谢

谢谢

编辑1:

换句话说,我使用一个Sql请求,比如“从表中全选”,然后将该数据作为JSON返回给我的应用程序

我如何申请一个小号码,然后添加其他号码等

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

  • 如果JSON非常大,您可以考虑使用“分页”比喻,即下载第一个x记录,然后对服务器数据的下一个“页面”发出后续请求。假设可以在请求之间添加额外的服务器记录,您必须仔细考虑该实现,但这可能很容易做到

  • 另一种提高JSON效率的方法是限制初始请求中返回的数据。例如,第一个请求可能只返回所有记录或合理记录子集的标识符或标题信息,然后您可能会有其他详细信息的后续请求(例如,用户进入详细信息屏幕)

  • 如果JSON当前包含任何大型数据元素(例如,Base64编码的二进制数据,如图像或声音文件),则前一点的一种特殊排列是。通过从最初的响应中获得这些信息,这将解决许多问题。如果你能返回这个二进制数据的URL,而不是数据本身,那肯定会让它自己延迟加载(同时也让你能够轻松下载二进制信息,而不是使用大于33%的Base64编码)。如果你在处理图像,你可能还想考虑缩略图和大图像的概念,尤其是在延迟加载模型中处理后者

  • 您可以考虑实现一个支持流的XML解析版本。标准的
    NSXMLParser
    实现尝试在解析进行之前,一次性将整个XML提要(或尽可能多地?)加载到内存中(尽管方法名称可能与此相反)。如果你的应用程序使用了
    LibXML2
    (比如苹果的),你可以在后台继续下载和解析XML,同时将初始数据呈现给用户。这将同时带来许多好处,大多数人将其与“延迟加载”(即,在向用户呈现结果之前,您不必等待一切)和“急切加载”(即,它将下载下一条记录,以便用户在访问时已经准备好)

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


    更新:

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

    其次,您需要更新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

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


    如果您使用的是
    UICollectionViewController
    ,则与上述代码类似。如果您使用的是滚动视图,则模式非常相似,尽管您将响应
    UIScrollViewDelegate
    方法
    scrollviewdidcoll
    (您不仅需要编写如上所述的代码,还需要编写一些可以释放屏幕上滚动的
    UIKit
    元素的代码)。

    这与Xcode无关。显然,我们需要一顶冬季Bash帽来移除“Xcode”标记……让它看起来像@H2CO3的化身。:)无论如何,这听起来像是你在应用程序服务器端设计中需要考虑的事情。它在做什么,需要重新设计