-1

I have a TableView that's constantly changing (cells are inserted and removed) inside a ScrollView. I have disabled scrolling for the TableView because there's a MapView above the TableView and I want to scroll the entire View, not just the TableView when the user scrolls up. Since cells are constantly being inserted and deleted into the TableView, the height for the TableView won't be fixed for the entire time the app is running.

I'm trying to constantly set the height of the TableView to match the height of the sum of the content inside by doing,

func someFunc() {

    // call viewDidAppear to update TableView
    viewDidAppear(true)

    // Calculate the size of the ScrollView
    var y: CGFloat = 10
    y = mapView.bounds.size.height + tableView.bounds.size.height + 10
    var sz = scrollView.bounds.size
    sz.height = y
    scrollView.contentSize = sz

}

// Update the TableView on main thread
override viewDidAppear(animated: Bool) {
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.tableView.reloadData()
        var frame: CGRect =  self.tableView.frame
        frame.size.height = self.tableView.contentSize.height
        self.tableView.bounds.size.height = frame.size.height
    })
}

However, tableView.bounds.size.height is not getting updated to the new height of content. Actually it updates sometimes, maybe once every few calls. I'm almost certain it's because dispatch_asyn() is an asynchronous method. So, I might need to return in the method to solve this, but I'm not sure how.

Am I doing this correctly to accomplish what I need? Is there a better way to do this? Any help is greatly appreciated.

Ivan
  • 665
  • 2
  • 10
  • 28

2 Answers2

0

I figured out how to do this, just in case any one else needs to implement something similar.

Once you've connected your Table View with an outlet and added the UITableViewDelegate and UITableViewDataSource protocols to your View Controller you can programmatically set the height of a Table View Cell by doing

self.tableView.rowHeight = 100.0

in your viewDidLoad().

Then, if you're Table View data is coming from an array, you can reset the height of your tableView to be

self.tableView.bounds.height = CGFloat(dataArray.count) * (self.tableView.rowHeight)

Notice how you have to cast the length of the dataArray to CGFloat because self.tableView.bounds.height is of Type CGFloat.

Now the height of your Table View is the height of the sum of all its cells.

Ivan
  • 665
  • 2
  • 10
  • 28
0

Even though Ivan's solution would work for equal and fixed-sized rows, it won't work if you are dealing with UITableViewAutomaticDimension and various heights for each row.

If you need the actual sum of all heights of rows, you can simply define a computational variable which returns height of tableView's contentSize after it updates the layout if needed.

var tableViewHeight: CGFloat {
    tableView.layoutIfNeeded()
    return tableView.contentSize.height
}

Using directly tableView.contentSize.height may cause you to have sum of estimated row heights instead of actual heights.

You can either use the variable I have given above or disable estimated heights if you don't need it as mentioned by an Apple developer here: Apple Developer Forum Discussion - UITableView's contentSize is wrong

A similar answer to a similar question already exists in StackOverFlow by the way. You can also check out here: Stackoverflow - Get Height of Table Contents in Swift

Yusuf Kamil AK
  • 771
  • 8
  • 17