简体   繁体   中英

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. 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
  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.

- (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.

I find it best, for now, to override the loadObjects function, which is called every time the tableView is refreshed. Just reload objects of the query into local datastore before loadObjects(0, clear: true)(Which handles refresh behaviors and hard to override) is called. (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.)

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)
    })
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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