Search code examples
iosfirebaseswift3firebase-realtime-databaseuirefreshcontrol

New added data in firebase database duplicate it self before pull to refresh using Swift3


Why when I'am adding new data to firebase database appears duplicated in my app , but when I pull down to make refresh its back again not duplicated , I put a Screenshot of how data appears in my project simulator .This is how data appears in my project 1

This is my Code.

 import UIKit
 import FirebaseDatabase
 import SDWebImage
 import FirebaseAuth


 class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate {


@IBOutlet weak var tableView: UITableView!

var Ref:FIRDatabaseReference?

var Handle:FIRDatabaseHandle?

var myarray = [Posts]()

var refresh = UIRefreshControl()

   override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

    refresh.addTarget(self, action: #selector(ViewController.loadData), for: .valueChanged)

    tableView.addSubview(refresh)


}

override func viewDidAppear(_ animated: Bool) {

    loadData()

    }



func loadData(){

    self.myarray.removeAll()

    Ref=FIRDatabase.database().reference()

    Handle = Ref?.child("Posts").queryOrdered(byChild: "Des").queryEqual(toValue: "11").observe(.childAdded ,with: { (snapshot) in

        if  let post = snapshot.value as? [String : AnyObject]{

            let img = Posts()

            img.setValuesForKeys(post)

            self.myarray.append(img)

            print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\(img)")

            self.tableView.reloadData()
        }


    })
      self.refresh.endRefreshing()

}

Solution

  • It appears self.refresh.endRefreshing() is being called outside the Firebase closure.

    This is bad as that code will run before Firebase returns the data and reloads the tableView data.

    Remember that Firebase is asynchronous and it takes time for the internet to get the data from the Firebase server to your app, so in-line code will usually execute before the code in the closure.

    Also, the Handle is unneeded in this case unless you are using it elsewhere.

    Ref?.child("Posts").queryOrdered(byChild: "Des").queryEqual(toValue: "11")
                       .observe(.childAdded ,with: { (snapshot) in
        if  let post = snapshot.value as? [String : AnyObject]{
            let img = Posts()
            img.setValuesForKeys(post)
            self.myarray.append(img)
            print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\(img)")
            self.tableView.reloadData()
        }
        self.refresh.endRefreshing()
    })
    

    Also, you may consider just removing the refreshing entirely as when you add an observer to a Firebase node (.childAdded) any time a child it added, your tableview will automatically refresh due to the code executed in the closure.