Collection or tableView inside a tableView cell broke in Mac Catalyst

Hello,

I'm using UITableViews with cells containing either a UICollectionView or UITableView in them. The cell's height is dependent on the content of the table/collectionView inside it. Think of it like the sections in the Settings app.

This all has been working fine for 2 years now (on iPhone/iPad/Mac running Mac Catalyst), but this week's macOS 12.5 release has caused every cell like this to have some items seemingly missing. However, clicking on a missing item will still have the correct action work, or moving the mouse around/above the missing cells, they will cause the correct content to appear.

Here's a code snippet of a tableView cell with a UITableView in it:

class SettingsCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource {
     @IBOutlet weak var contentTable: UITableView!
     //Height constant of tableView in cell
     @IBOutlet weak var contentTableHeightConstraint: NSLayoutConstraint!

     private var _type: SettingType = .unknown

     override func awakeFromNib() {
          super.awakeFromNib()
          
          contentTable.delegate = self
          contentTable.dataSource = self
          contentTable.isScrollEnabled = false

          contentTable.register(UINib(nibName: "SettingsRowCell", bundle: nil), forCellReuseIdentifier: "SettingsRowCell")
          contentTable.estimatedRowHeight = 45.0
          contentTable.rowHeight = UITableView.automaticDimension

          layoutIfNeeded()
          contentTableHeightConstraint.constant = contentTable.contentSize.height
     }

     //This is called in the cellforRowAt method in the parent table where it chooses which type of settings section to show
     func updateWithType(type: SettingType) {
          _type = type

          contentTable.reloadData()
          layoutIfNeeded()
          contentTableHeightConstraint.constant = contentTable.contentSize.height
     }

     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
          if type == .general {
               return generalArray.count
          } else if type == .notifications {
               return notifArray.count
          }
        
          return 0
    }

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

The issue seems to steam from a tableView or collectionView being inside a tableViewCell because happens to all my cells like this.

I've been digging through the code for days, and nothing is out of the ordinary. I never hide any of the cell's content in any scenario, so this isn't the normal reusable cell issue where the content needs to be set back to being visible.

Does anyone know of the fix this or has any pointers? Also, these cells work as normal on iPhone/iPad. I've been trying to figure this out for a long time, and any help would be greatly appreciated!

Post not yet marked as solved Up vote post of helper132 Down vote post of helper132
1.2k views

Replies

Can you post a screenshot of the app when this fails?

I would advice against putting multiple scroll views (like table views) inside each other that are scrolling in the same direction. If you get the content offset wrong by just a single point, the scrolling interaction can break and feel very off. In addition to that, table views and collection views are specifically problematic, especially when used with estimated sizes, because you don't know the height of the inner table or collection view unless you load every cell. However due to how layout in those classes works, you can not get this size with a single query. You essentially have to keep expanding the view to the content size, trigger layout again and see if the content size changed in a loop until the size stabilizes.