0

I am trying to retrieve data from Firebase database in a UITableView it's working good , But i need to present another ViewController and dismiss it and back to my TableView data duplicated

here's my code :

    import UIKit
    import Firebase
    import FirebaseDatabase


    class AddEditRosterViewController: UIViewController {



        // MARK: - Properties 

        var students = [Student]()

        var tempStudents = [Student]()
        var studentsDict = [String:[Student]]()
        var sectionLetters = [String]()

    var allLetters = ["A" , "B" , "C" , "D" , "E" , "F" , "G" , "H" , "I" , "J" , "K" , "L" , "M" , "N" , "O" , "P" , "Q" , "R" , "S" , "T"  , "U" , "V" , "W" , "X" , "Y" , "Z"]
    var sections = [String]()

        var ref:DatabaseReference!
override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        // set databse ref 

       ref = Database.database().reference()

}


    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        if self.studentsDict.count == 0
        {
            self.retrivedData()
        }


    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillAppear(animated)

        self.studentsDict.removeAll()
        self.students.removeAll()
        self.tempStudents.removeAll()
        self.sections.removeAll()


    }


func retrivedData()

{
 showLoaderForController(self)
            StudentsViewModel.shared.getAllUsers(completion: { res , data in
                hideLoaderForController(self)


                if res == true
                {



                    self.students = data
                    self.tempStudents = data
                    for student in self.students
                    {
                        let firstname = student.firstname!
                        let key = firstname.substring(to: 1)
                        let lower = key.lowercased()

                        if var wordValues = self.studentsDict[lower]
                        {
                            wordValues.append(student)
                            self.studentsDict[lower] = wordValues
                        }else
                        {
                            self.studentsDict[lower] = [student]
                        }
                    }

                    self.sectionLetters = [String] (self.studentsDict.keys).sorted()


                    self.tableView.reloadData()


                }

                self.tableView.reloadData()


            })
extension  AddEditRosterViewController : UITableViewDelegate , UITableViewDataSource
{


    // MARK: - Table view data source

     func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections



        var numOfSections: Int = 0
        if self.sectionLetters.count > 0
        {
            tableView.separatorStyle = .singleLine
            numOfSections            = self.sectionLetters.count
            tableView.backgroundView = nil
        }
        else
        {
            let noDataLabel: UILabel     = UILabel(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
            noDataLabel.text          = "There are no students found"
            noDataLabel.font =  UIFont(name: "Avenir Next Medium", size: 19)!
            noDataLabel.textColor     = UIColor.black
            noDataLabel.textAlignment = .center
            tableView.backgroundView  = noDataLabel
            tableView.separatorStyle  = .none
        }
        return numOfSections


    }


     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows

        let wordKey = self.sectionLetters[section]

        if let wordValues = self.studentsDict[wordKey]
        {
            return wordValues.count
        }
        return 0
    }


     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "userCell", for: indexPath) as! SearchUserTableViewCell
        let wordKey = sectionLetters[indexPath.section]
        if let students = self.studentsDict[wordKey]
        {

            let student = students[indexPath.row]
            cell.fullName.text = "\(student.firstname!) \(student.lastname!)"
            cell.location.text = student.currentLocation.location!

            cell.userImage.sd_setImage(with: URL(string: student.image!), placeholderImage: #imageLiteral(resourceName: "Profile"))



        }




        return cell
    }



}

and here's Controller method

 func getAllUsers(completion:@escaping(_ result:Bool , _ data : [Student]) -> () )
    {
         ref = Database.database().reference()
        // array to save values

        var array = [Student]()


        ref.child("students").observe(.value, with: { snapshot in

            if snapshot.exists()
            {

                // snapshots
                for snap in snapshot.children {


                    let userSnap = snap as! DataSnapshot
                    //  let uid = userSnap.key //the uid of each user
                    let userDict = userSnap.value as! [String:AnyObject]

                    let student = Student()
                    student.id = userSnap.key
                    student.firstname = userDict["first_name"] as? String
                    student.lastname = userDict["last_name"] as? String
                    student.email = userDict["email"] as? String
                    student.mobile = userDict["mobile"] as? String
                    student.dorm = userDict["dorm"] as? String
                    student.form = userDict["form"] as? Int
                    student.gender = userDict["gender"] as? String
                    student.image = userDict["profile_picture"] as? String
                    student.currentLocation.location = userDict["current_location"] as? String
                    student.grade = userDict["grade"] as? Int






                    array.append(student)

                }


                completion(true, array)

            }else
            {
                completion(false, [])
            }
        })


    }

I am just need to call retrivedData() every time the view didAppear

but remove first the old data and replace with the new data

Muhammed
  • 584
  • 1
  • 11
  • 24
  • i think you need to use singleObserv to retrive data coz what you used that called each time and you append data in array each time. so either you need to nil array and add again or use singleObserv – Nitin Gohel Feb 08 '18 at 08:28
  • just not tried singleObserv but didn't work and i already remove the array before i append again – Muhammed Feb 08 '18 at 08:32

2 Answers2

0

When calling the firebase db observer, remove all the objects from array in your controller method and then append after parsing.

Do it like this.

Aryan Sharma
  • 625
  • 2
  • 9
  • 24
0

Try also to remove the observer before you add another. It seems that when any change happen, the observer function is called more than one time.

var firebaseObservationHandle: UInt?    

func getAllUsers(completion:@escaping(_ result:Bool , _ data : [Student]) -> () )
{

    ref = Database.database().reference()

    if let handle = firebaseObservationHandle {
        ref.removeObserver(withHandle: handle)
    }

    var array = [Student]()


    firebaseObservationHandle = ref.child("students").observe(.value, with: { snapshot in

        ...

    }
}

Also make sure removal of the data before appending any other data.

user9335240
  • 1,739
  • 1
  • 7
  • 14