Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make UIRefreshControl end refreshing when finish loading from Firebase

The following method is my refreshing data method. It will read from the firebase to get the newest data. Because firebase is unsynchronized so I wait 5 seconds before endRefreshing to wait for Firebase to finish the reading process.

func refreshData() {
    //Remove old data
    self.items.removeAll()
    //Renew all data
    var ref: DatabaseReference!
    ref = Database.database().reference(withPath: "tasks")
    //Loading local drafts
    var drafts : [Task]!
    if let local_drafts = NSKeyedUnarchiver.unarchiveObject(withFile: Task.ArchiveURL.path) as? [Task] {
        drafts = local_drafts
    }
    else{
        drafts = []
    }
    //Reloading the database
    ref.observe(.value, with: { snapshot in
        var newItems: [Task] = []
        self.num_of_tasks = Int(snapshot.childrenCount)
        for item in snapshot.children {
            //let local = item as! DataSnapshot
            //let snapshotValue = local.value as! [String: AnyObject]
            //print(snapshotValue["main_content"] as! String!)
            let taskItem = Task(snapshot: item as! DataSnapshot)
            newItems.append(taskItem!)
        }
        let merged = drafts + newItems
        self.items = merged
        self.tableView.reloadData()
        //Wait for 5 seconds
        let deadlineTime = DispatchTime.now() + .seconds(3)
        DispatchQueue.main.asyncAfter(deadline: deadlineTime, execute: {
            self.refreshControl!.endRefreshing()
        })
    })
}

But this is not a good solution because sometimes all data is loaded but the refreshing is still continuing, which makes it strange. Is there a way to solve this kind of situation? Make the refreshControl end refreshing until I load all data from firebase?

like image 908
Patroclus Avatar asked Oct 31 '25 13:10

Patroclus


1 Answers

Beneath is one way to do it. It will wait until the async data has finished downloaded, and than when the completionHandler return either true or false, the refreshControl will stop refresh. I do not had a compiler here so I hope it works without errors.

func viewDidLoad(){
refreshData{ _ in
    self.refreshControl!.endRefreshing()
}
}

func refreshData(completionHandler:@escaping (Bool)->() ) {
    //Remove old data
    self.items.removeAll()
    //Renew all data
    var ref: DatabaseReference!
    ref = Database.database().reference(withPath: "tasks")
    //Loading local drafts
    var drafts : [Task]!
    if let local_drafts = NSKeyedUnarchiver.unarchiveObject(withFile: Task.ArchiveURL.path) as? [Task] {
        drafts = local_drafts
    }
    else{
        drafts = []
    }
    //Reloading the database
    ref.observe(.value, with: { snapshot in
        var newItems: [Task] = []
        self.num_of_tasks = Int(snapshot.childrenCount)
        for item in snapshot.children {
            //let local = item as! DataSnapshot
            //let snapshotValue = local.value as! [String: AnyObject]
            //print(snapshotValue["main_content"] as! String!)
            let taskItem = Task(snapshot: item as! DataSnapshot)
            newItems.append(taskItem!)
        }
        let merged = drafts + newItems
        self.items = merged
        self.tableView.reloadData()
        completionHandler(true)
    })
}
like image 89
J. Doe Avatar answered Nov 02 '25 03:11

J. Doe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!