0

I'm using the tableView.backgroundView to set some default text when my array is empty and there's no data to feed to the tableView. The code works.

The problem is that EVEN If there's data, first it sort of flashes the "No results" for a split of a second but quite obvious and then the tableView is being reloaded with actual data from the array. How can I fix this?

func numberOfSections(in tableView: UITableView) -> Int {
    var numOfSections: Int = 1
    if comments.count > 0 {
        numOfSections            = 1
        tableView.backgroundView  = nil
    }
    else {
        numOfSections = 0
        activityIndicator.stopAnimating()
        let noDataLabel: UILabel     = UILabel(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
        noDataLabel.text          = "Silence in the comments! \r\nSay something..."
        noDataLabel.textColor     = UIColor.black
        noDataLabel.textAlignment = .center
        tableView.backgroundView  = noDataLabel
        tableView.backgroundView?.backgroundColor = UIColor.hex("D8D8D8")
        tableView.separatorStyle  = .none
    }
    return numOfSections
}

UPDATE:

Even when I add it in the place where it gets the data from, the same thing happens again. The no data state flashes first and its obvious and then it shows the actual results. The function below is called in the viewWillAppear

func loadComments() {
        activityIndicator.startAnimating()

        if let id = postId {

            Api.Post_Comment.REF_POST_COMMENTS.child(id).observe(.childAdded, with: {
                snapshot in

                Api.Comment.observeComments(withPostId: snapshot.key) {
                    comment in
                    self.fetchUser(uid: comment.uid!, completed: {
                        self.comments.append(comment)
                        self.activityIndicator.stopAnimating()
                        self.tableView.reloadData()

                        if self.comments.count > 0 {
                            self.numOfSections = 1
                            self.tableView.backgroundView  = nil
                        }
                        else {
                            print("ELSE")
                        }
                    })
                }
            })
            print("No data")
            self.numOfSections = 0
            self.activityIndicator.stopAnimating()
            let noDataLabel: UILabel  = UILabel(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: self.tableView.bounds.size.height))
            noDataLabel.numberOfLines = 0
            noDataLabel.text         = "Silence in the comments! \r\nSay something..."
            noDataLabel.textColor     = UIColor.darkGray
            noDataLabel.textAlignment = .center
            self.tableView.backgroundView  = noDataLabel
            self.tableView.backgroundView?.backgroundColor = UIColor.hex("D8D8D8")
            self.tableView.separatorStyle  = .none

        }

    }
Dani
  • 3,427
  • 3
  • 28
  • 54
  • 2
    None of that code belongs in `numberOfSections` except the few lines that set the count. `numberOfSections` can be called many, many times at any time during the use of the table view. – rmaddy Jun 04 '18 at 18:12
  • Okay, I guess that was a mistake. That was a top answer here by the way - https://stackoverflow.com/a/28533438/4700495 How should I do it then? – Dani Jun 04 '18 at 18:14
  • 1
    Put most of that code where it belongs - where you load your data and populate `comments`. – rmaddy Jun 04 '18 at 18:16
  • Most of the answers from that link are wrong despite all of the votes. – rmaddy Jun 04 '18 at 18:16
  • Well, I've tried what you've suggested and either I'm not doing something right or it doesn't work. Because the effect seems to be the same. See my updated question, now I've set up the `numberOfSections` method to simply `return numOfSections` as I've made the var global and it's accessible to the `loadComments` function – Dani Jun 04 '18 at 18:48
  • You could try putting the `tableView.backgroundView` code (at the bottom of your `loadComments()` method) into a `DispatchQueue.main.asyncAfter(deadline: .now()+0.5) { }` block. – Chris Jun 04 '18 at 19:16

1 Answers1

0

There may be a cleaner way to do this in one of the tableView delegate methods, but a simple delayed animation to present the label within your loadComments() method will achieve the effect you want.

let noDataLabel: UILabel  = UILabel(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: self.tableView.bounds.size.height))

noDataLabel.alpha = 0
noDataLabel.numberOfLines = 0
noDataLabel.text = "Silence in the comments! \r\nSay something..."
noDataLabel.textColor = UIColor.darkGray
noDataLabel.textAlignment = .center
noDataLabel.backgroundColor = UIColor.hex("D8D8D8")
self.tableView.backgroundView = noDataLabel
self.tableView.separatorStyle = .none

UIView.animate(withDuration: 0.5, delay: 0.5, animations: {
    self.noDataLabel.alpha = 1
})
Chris
  • 4,009
  • 3
  • 21
  • 52