Search code examples
iosswiftcloudkitpull-to-refresh

Pull to Refresh: data refresh is delayed


I've got Pull to Refresh working great, except when the table reloads there is a split second delay before the data in the table reloads.

Do I just have some small thing out of place? Any ideas?

viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
    self.refreshControl?.addTarget(self, action: "handleRefresh:", forControlEvents: UIControlEvents.ValueChanged)
    self.getCloudKit()
}

handleRefresh for Pull to Refresh:

func handleRefresh(refreshControl: UIRefreshControl) {    
    self.objects.removeAll()
    self.getCloudKit()
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        refreshControl.endRefreshing()
    })
}

Need the data in two places, so created a function for it getCloudKit:

func getCloudKit() {
    publicData.performQuery(query, inZoneWithID: nil) { results, error in
        if error == nil { // There is no error
            for play in results! {
                let newPlay = Play()
                newPlay.color = play["Color"] as! String
                self.objects.append(newPlay)
            }

            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.tableView.reloadData()
            })

        } else {
            print(error)
        }
    }
}

tableView:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
    let object = objects[indexPath.row]
    if let label = cell.textLabel{
        label.text = object.matchup
    }
    return cell
}

Solution

  • This is how you should do this:

    1. In your handleRefresh function, add a bool to track the refresh operation in process - say isLoading.
    2. In your getCloudKit function just before reloading the table view call endRefreshing function if isLoading was true.
    3. Reset isLoading to false.
    4. Importantly - Do not remove your model data before refresh operation is even instantiated. What if there is error in fetching the data? Delete it only after you get response back in getCloudKit function.
    5. Also, as a side note, if I would you, I would implement a timestamp based approach where I would pass my last service data timestamp (time at which last update was taken from server) to server and server side would return me complete data only there were changes post that timestamp else I would expect them to tell me no change. In such a case I would simple call endRefreshing function and would not reload data on table. Trust me - this saves a lot and gives a good end user experience as most of time there is no change in data!