0

I am making this app where users can give feedback on other users resumes. I have the feedback stored in a firebase realtime database. In my FeedbackViewController, I have a tableview and need to access the totalFeedbackNum on my database in order to populate my tableview, however I am getting an error. The commented code below is what the code should be but it's throwing the error: Unexpected non-void return value in void function.

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

//        var ref: DatabaseReference!
//        ref = Database.database().reference()
//        let uid = Auth.auth().currentUser?.uid
//        ref.child("usernames/\(uid!)/profile/feedback/totalFeedbackNum").observeSingleEvent(of: .value, with: { (snapshot) in
//            let value = snapshot.value as? NSDictionary
//            let totalFeedbackNum = value?["totalFeedbackNum"] as? Int ?? 0
//            return totalFeedbackNum //this throws "Unexpected non-void return value in void function"
//        }) { (error) in
//            print(error.localizedDescription)
//        }

        let totalFeedbackNum = 3
        return totalFeedbackNum
    }

I think I should be using a completion handler but I don't know how. I'm working with Swift 5.

Edit: I followed the first link in the comments and got this but still it's not working:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        let uid = Auth.auth().currentUser?.uid
        var ref: DatabaseReference!
        ref = Database.database().reference()
        var totalFeedbackNum = 1
        print("Starting observing")
        ref.child("usernames/\(uid!)/profile/feedback/totalFeedbackNum").observe(.value, with: { (snapshot: DataSnapshot!) in
            print("Got snapshot")
            let value = snapshot.value as? NSDictionary
            totalFeedbackNum = value?["totalFeedbackNum"] as? Int ?? 0
        })
        print("Returning totalFeedbackNum: \(totalFeedbackNum)");
        return totalFeedbackNum
    }

This code prints: Starting observing Returning totalFeedbackNum: 1 Starting observing Returning totalFeedbackNum: 1 Got snapshot Got snapshot

Jack Antico
  • 31
  • 1
  • 6
  • You'll indeed want to call the completion handler once you get data back from Firebase. See https://stackoverflow.com/a/37925384, https://stackoverflow.com/questions/52972911/swift-completion-handler-with-firebase/52973061#52973061, https://stackoverflow.com/a/56314312 and probably more from this list: https://stackoverflow.com/search?q=%5Bfirebase-realtime-database%5D%5Bswift%5D+asynchronous – Frank van Puffelen Jan 28 '20 at 15:12
  • I tried the first link but it didn't work, how should I tweak the edited code that I added to the question? Thanks for your comment – Jack Antico Jan 28 '20 at 16:03
  • 1
    Never ever load data asynchronously in `numberOfRows`. Load the records (once) in `viewDidLoad` into an array and return `.count` in `numberOfRows`. – vadian Jan 28 '20 at 16:07
  • How would I then pass the data to numerOfRows? – Jack Antico Jan 28 '20 at 16:10
  • In `numberOfRows` you have to return the number of items in the data source array, nothing else. – vadian Jan 28 '20 at 16:14
  • Got it, sorry, so then how would I load the data in viewDidLoad? – Jack Antico Jan 28 '20 at 16:16
  • This depends on your data model. – vadian Jan 28 '20 at 16:16
  • You'd load it in the same way, no matter where in your app you do that. The difference is that from `viewDidLoad`, you'd store the count in a member field, e.g. `self.totalFeedbackNum`. Then all that `numberOfRowsInSection` does, is `return self.totalFeedbackNum`. – Frank van Puffelen Jan 28 '20 at 17:33

1 Answers1

0

Okay, so I figured it out. As vadian pointed out, I needed to declare a totalFeedbackNum global variable which I initially set to 0. The do the following in viewDidLoad:

override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self

        let uid = Auth.auth().currentUser?.uid
        var ref: DatabaseReference!
        ref = Database.database().reference()

        ref.child("users/\(uid!)/profile/feedback/totalFeedbackNum").observeSingleEvent(of: .value, with: { (snapshot) in
            let value = snapshot.value as? NSDictionary
            self.totalFeedbackNum = value?["totalFeedbackNum"] as? Int ?? 0
            self.tableView.reloadData()
        }) { (error) in
            print(error.localizedDescription)
        }
    }

Hope this can help someone. Cheers, Jack

Jack Antico
  • 31
  • 1
  • 6