Daibaku
Daibaku

Reputation: 12576

Call reloadData() in the right place

I'm trying to fetch data from firebase and pass to tableview.

 // Model
          import UIKit
          import Firebase

              struct ProfInfo {

                  var key: String
                  var url: String
                  var name: String

                     init(snapshot:DataSnapshot) {

                         key = snapshot.key
                         url = (snapshot.value as! NSDictionary)["profileUrl"] as? String ?? ""
                         name = (snapshot.value as! NSDictionary)["tweetName"] as? String ?? ""
                }
           }

   // fetch 
            var profInfo = [ProfInfo]()

            func fetchUid(){
                    guard let uid = Auth.auth().currentUser?.uid else{ return }
                    ref.child("following").child(uid).observe(.value, with: { (snapshot) in
                        guard let snap = snapshot.value as? [String:Any] else { return }
                        snap.forEach({ (key,_) in
                            self.fetchProf(key: key)
                        })
                    }, withCancel: nil)
                }

                func fetchProf(key: String){
                    var outcome = [ProfInfo]()
                        ref.child("Profiles").child(key).observe(.value, with: { (snapshot) in
                                let info = ProfInfo(snapshot: snapshot)
                                outcome.append(info)
                            self.profInfo = outcome
                            self.tableView.reloadData()
                        }, withCancel: nil)
                }

   //tableview
            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                    return profInfo.count
                }

                func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

                    let cell = tableView.dequeueReusableCell(withIdentifier: "followCell", for: indexPath) as! FollowingTableViewCell

                    cell.configCell(profInfo: profInfo[indexPath.row])

                    return cell
                }

However it returns one row but profInfo actually has two rows. when I implement print(self.profInfo) inside fetchProf it returns two values. But after passed to tableview, it became one. I'm not sure but I guess the reason is that I put reloadData() in the wrong place because I hit break point and reloadData() called twice. So, I think profInfo replaced by new value. I called in different places but didn't work. Am I correct? If so, where should I call reloadData()? If I'm wrong, how can I fix this? Thank you in advance!

Upvotes: 0

Views: 174

Answers (4)

Y_Y
Y_Y

Reputation: 341

You need to append the new data to the profinfo array. Simply replace the fetchProf method with this:-

func fetchProf(key: String){     
         var outcome = [ProfInfo]()          
         ref.child("Profiles").child(key).observe(.value, with: {  (snapshot)   in    
         let info = ProfInfo(snapshot: snapshot)           
         outcome.append(info)     
         self.profInfo.append(contentOf: outcome)      
         Dispatch.main.async{
         self.tableView.reloadData()    
        }  
    } , withCancel: nil) 
}

Upvotes: 1

Faysal Ahmed
Faysal Ahmed

Reputation: 7669

Table view showing one content because when table view reloaded then profile info not combine all data. You need to reload the table view after combining all data. This will help you.

// fetch 
        var profInfo = [ProfInfo]()

        func fetchUid(){
                guard let uid = Auth.auth().currentUser?.uid else{ return }
                ref.child("following").child(uid).observe(.value, with: { (snapshot) in
                    guard let snap = snapshot.value as? [String:Any] else { return }
                    snap.forEach({ (key,_) in
                        self.fetchProf(key: key)
                    })
                  // When all key fetched completed the just reload the table view in the Main queue 
                   Dispatch.main.async{
                       self.tableView.reloadData()    
                     }

                }, withCancel: nil)
            }

            func fetchProf(key: String){
                    ref.child("Profiles").child(key).observe(.value, with: { (snapshot) in
                        let info = ProfInfo(snapshot: snapshot)
                        self.profInfo.append(info) // Here just add the outcome object to profileinfo
                    }, withCancel: nil)
            }

This way no need to handle another array.

Upvotes: 1

iOS Geek
iOS Geek

Reputation: 4855

if you notice one thing in the following function you will see

func fetchProf(key: String){
                    var outcome = [ProfInfo]()
                        ref.child("Profiles").child(key).observe(.value, with: { (snapshot) in
                                let info = ProfInfo(snapshot: snapshot)
                                outcome.append(info)

 //Here 
 /You are replacing value in self.profInfo
 //for the first time when this is called it results In First profile info
 //When you reload here first Profile will be shown 
 //Second time when it is called you again here replaced self.profInfo 
 //with second Outcome i.e TableView reloads and output shown is only second Profile
 //you had initialised a Array self.profInfo = [ProfInfo]()
 //But you just replacing array with Single value Actually you need to append data
 // I think here is main issue

 self.profInfo = outcome


 //So try Appending data as 
 //self.profInfo.append(outcome) instead of self.profInfo = outcome
 //Then reload TableView to get both outputs
 self.tableView.reloadData()

   }, withCancel: nil)
}

Upvotes: 1

Lou Franco
Lou Franco

Reputation: 89192

self.tableView.reloadData() must be called from the main queue. Try

DispatchQueue.main.async {
    self.tableView.reloadData()
}

Upvotes: 1

Related Questions