简体   繁体   English

Parse.com PFQueryTableViewController本地数据存储

[英]Parse.com PFQueryTableViewController Local datastore

I have a Swift app in which I have a PFQueryTableViewController , and I'd like to use the local datastore with Parse. 我有一个Swift应用程序,其中有PFQueryTableViewController ,我想将本地数据存储与Parse一起使用。 But, I'm getting confused about using the local datastore alongside live queries. 但是,我对将本地数据存储与实时查询一起使用感到困惑。

Here is what I'd like to do: 这是我想做的:

  1. When the PFQueryTableViewController is shown, I'd like it to always get data from the local datastore 显示PFQueryTableViewController ,我希望它始终从本地数据存储中获取数据
  2. But, after the view is rendered with no lag (since the local data store is powering the source of the data), I want to make an asynchronous call to update the local data store with most updated data from the cloud. 但是,在没有滞后地渲染视图之后(因为本地数据存储为数据源提供了动力),我想进行异步调用,以使用云中最新的数据更新本地数据存储。 At this point, if there is new data, I'd like the most updated data to appear in the table seamlessly and preferably with row animation. 在这一点上,如果有新数据,我希望最新的数据无缝地出现在表中,最好与行动画一起出现。

How do I achieve this? 我该如何实现?

Here's how I managed this - maybe it will put you on the right track. 这是我的处理方式-也许它将使您走上正确的道路。 I'd be interested to see your solution if you have already fixed the problem. 如果您已解决问题,我很想看看您的解决方案。

First, I made a convenience method to create my base query: 首先,我提供了一种方便的方法来创建基本查询:

- (PFQuery *)baseQuery
{
    PFQuery *query = [PFQuery queryWithClassName:@"MyClass"];
    [query orderByDescending:@"myParameter"];
    return query;
}

We want queryForTable to hit the local datastore consistently. 我们希望queryForTable能够始终访问本地数据存储。

- (PFQuery *)queryForTable
{
    return [[self baseQuery] fromLocalDatastore];
}

So now all that's left to do is populate the local datastore from the network: 所以现在剩下要做的就是从网络填充本地数据存储:

- (void)refreshObjects
{
    [[[self baseQuery] findObjectsInBackground] continueWithBlock:^id(BFTask *task) {
        if (task.error) {
            [self.refreshControl endRefreshing];
            return nil;
        }
        return [[PFObject unpinAllObjectsInBackgroundWithName:@"cacheLabel"] continueWithSuccessBlock:^id(BFTask *unused) {
            NSArray *objects = task.result;
            return [[PFObject pinAllInBackground:objects withName:@"cacheLabel"] continueWithSuccessBlock:^id(BFTask *unused) {
                [self.refreshControl endRefreshing];
                [self loadObjects];
                return nil;
            }];
        }];
    }];
}

We can call this whenever we want: in viewDidLoad or viewDidAppear , in response to a pull-to-refresh event (which is why I have the UIRefreshControl code in there) or whenever else it might be appropriate. 我们可以在任何需要的时候调用它:在viewDidLoadviewDidAppear ,响应于pull-to-refresh事件(这就是为什么我在那里有UIRefreshControl代码的原因)或其他任何合适的情况。

I find it best, for now, to override the loadObjects function, which is called every time the tableView is refreshed. 我现在发现最好重写loadObjects函数,该函数在每次刷新tableView时都会调用。 Just reload objects of the query into local datastore before loadObjects(0, clear: true)(Which handles refresh behaviors and hard to override) is called. 只需在调用loadObjects(0,clear:true)(可处理刷新行为且难以覆盖)之前将查询的对象重新加载到本地数据存储中。 (This should work fine with internet connection, or after refresh all the objects will be void. You need to add some of your own logic for perfection.) (这在Internet连接上应该可以正常工作,或者刷新后所有对象都将无效。您需要添加一些自己的逻辑以求完美。)

var firstTime : Bool = true

//MARK: Query
func basicQuery() -> PFQuery {
    let query = PFQuery(className: "CLASSNAME")
    return query.orderByAscending("params")
}

override func queryForTable() -> PFQuery {
    return basicQuery().fromLocalDatastore()
}

//MARK: - Refresh
//TODO: Should consider the condition with no internet connection
override func loadObjects() -> BFTask {
    if firstTime { 
    // Load frome local data store
        firstTime = false
        return loadObjects(0, clear: true)
    }

    return queryForTable().findObjectsInBackground().continueWithBlock({ (task : BFTask!) -> AnyObject! in
        if task.error != nil { // No object in local data store
            return nil
        }
        if let objects = task.result as? [PFObject] { // Unpin local datastore objects
            return PFObject.unpinAllInBackground(objects, withName: "cacheString")
        }
        return nil
    }).continueWithSuccessBlock({ (task : BFTask!) -> AnyObject! in
        // Fetch objects from Parse
        return self.basicQuery().findObjectsInBackground()
    }).continueWithSuccessBlock({ (task : BFTask!) -> AnyObject! in
        if let objects = task.result as? [PFObject] {
            return PFObject.pinAllInBackground(objects, withName: "cacheString")
        }
        return nil
    }).continueWithSuccessBlock({ (task : BFTask!) -> AnyObject! in
        return self.loadObjects(0, clear: true)
    })
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM