1

I have a UICollectionView inside a UITableViewCell.

I am setting the UITableViewCell row height to be dynamic:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
   return UITableViewAutomaticDimension
}

My UICollectionView has a variable number of items:

func collectionView(_ collectionView: UICollectionView,
                    numberOfItemsInSection section: Int) -> Int {
    return items.count
}

Now here is the sequence of events that is causing me headache:

  • UITableView calls delegate cellForRowAt and dequeues a UITableViewCell with dynamic height
  • In the NEXT loop cycle, the UICollectionView inside the UITableViewCell calls on its delegates numberOfItemsInSection and cellForItemAt to determine the UICollectionView contentSize.
  • Now it's too late since the UITableViewCell has already been dynamically sized with a UICollectionView that has no cells, and so the UITablewViewCell height is too short and does NOT fit the UICollectionView properly.

I have found an ugly work around by reloading the UITableView but I don't like this approach at all:

private func reloadCell() {
    let when = DispatchTime.now()
    DispatchQueue.main.asyncAfter(deadline: when) {
        if let indexPath = self.chatViewController?.chatTableView.indexPath(for: self) {
            self.tableView.reloadRows(at: [indexPath], with: .none)
        }
    }
}

My question is if I can force the UICollectionView to reload and call it's delegates immediately so that the UITableViewCell height can be computed by the autolayout engine correctly?

4
  • Is your collection view height dynamic or tableview cell height? Commented Dec 4, 2016 at 9:39
  • The UICollectionView height is dynamic (depends on number of items) and therefore the UITableViewCell (which contains the UICollectionView) is also dynamic Commented Dec 4, 2016 at 9:41
  • 1
    Did you ever manage to find a solution for this, I currently have this issue. Commented Apr 19, 2018 at 22:19
  • Create a subclass for collection view and override the intrinsicContentSize. Refer here Commented Sep 9, 2018 at 18:47

1 Answer 1

0

In viewDidLoad, add observer for collection view,

 collectionView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.Old.union(NSKeyValueObservingOptions.New), context: self)

Now, overrider observe value for keypath for controlling collection view reload completion handler through KVO.

 override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) 
 {
    // You will get here when the reloadData finished 
 }

Now, in view Will Disappear remove observer that was set for collection view.

 override func viewWillDisappear(_ animated: Bool) {
 {
   // remove collection view observer   
 }

Same logic will be applied for tableview in order to get fully visible tableview cell containing collection view inside it.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.