One cell disappears from UICollectionView if height changed in process

I wanted to implement a self-sizing horizontal UICollectionView with self-sizing cells. I used the observer on "contentSize" of collectionView, so that when I change Dynamic Type size, the collection view resizes together with cells. But when I change the number of items to 1. The single cell disappears!

The bug is reproducible when the estimatedItemSize = UICollectionViewFlowLayout.automaticSize, but if set some concrete value (e.g. CGSize(width: 100, height: 20)) everything works as expected. But I assume that automaticSize should have worked no matter how many cells need to be displayed.

Environment: Simulator iPhone 15 Pro, iOS 17.0.1, Xcode 15.0.1

I've created a bug report. Bug Number: FB13379594

//  ViewController.swift

import UIKit

class ViewController: UIViewController {
    var items: [String] = []
    
    var horizontalInset: CGFloat = 10
    
    var verticalInset: CGFloat = 5
    
    @IBOutlet weak var collectionView: UICollectionView!
    
    @IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.estimatedItemSize = UICollectionViewFlowLayout.automaticSize // This causes One cell to disappear
        
//        (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.estimatedItemSize = CGSize(width: 100, height: 20) // This works
        
        setOneItem()
//        setMultipleItems()
        
        collectionView.dataSource = self
        
        let horizontalCollectionViewFlowLayout = UICollectionViewFlowLayout()
        horizontalCollectionViewFlowLayout.scrollDirection = .horizontal
        collectionView.collectionViewLayout = horizontalCollectionViewFlowLayout
        
        let cellIdentifier = String(describing: HorizontalCollectionViewCell.self)
        let nib = UINib(nibName: cellIdentifier, bundle: nil)
        collectionView.register(nib, forCellWithReuseIdentifier: cellIdentifier)
        
        collectionView.contentInset = UIEdgeInsets(
            top: verticalInset,
            left: horizontalInset,
            bottom: verticalInset,
            right: horizontalInset
        )
        collectionView.horizontalScrollIndicatorInsets.left = 5
        collectionView.horizontalScrollIndicatorInsets.right = 5
        
        collectionView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
    }
    
    @IBAction func setOneItem(_ sender: UIButton) {
        setOneItem()
        collectionView.reloadData()
    }
    
    @IBAction func setMultipleItems(_ sender: UIButton) {
        setMultipleItems()
        collectionView.reloadData()
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
        if (object as? UICollectionView) == collectionView,
           keyPath == "contentSize" {
            setupCollectionViewHeight()
        }
    }
    
    private func setOneItem() {
        items = ["One"]
    }
    
    private func setMultipleItems() {
        items = [
            "One",
            "Two Two",
            "Three Three Three",
            "Four Four Four Four",
            "Five Five Five Five",
            "Six Six Six Six Six Six"
        ]
    }
    
    private func setupCollectionViewHeight() {
        if collectionView.contentSize.width != 0,
           let layoutAttributes = firstItemLayoutAttributes() {
            collectionViewHeightConstraint.constant = layoutAttributes.size.height + verticalInset * 2
        }
    }
    
    private func firstItemLayoutAttributes() -> UICollectionViewLayoutAttributes? {
        guard collectionView.numberOfSections > 0,
              collectionView.numberOfItems(inSection: 0) > 0,
              let layoutAttributes = collectionView.collectionViewLayout.layoutAttributesForItem(at: IndexPath(row: 0, section: 0)),
              layoutAttributes.size.height > 0 else { return nil }
        return layoutAttributes
    }
}

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cellIdentifier = String(describing: HorizontalCollectionViewCell.self)
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as? HorizontalCollectionViewCell else {
            return UICollectionViewCell()
        }
        let item = items[indexPath.row]
        cell.titleLabel.text = item
        return cell
    }
}

//  HorizontalCollectionViewCell.swift

import UIKit

class HorizontalCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var titleLabel: UILabel!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        titleLabel.font = UIFont.preferredFont(forTextStyle: .body) // Dynamic Type Font
        titleLabel.adjustsFontForContentSizeCategory = true // Automatically Adjusts Font
    }
    
}
One cell disappears from UICollectionView if height changed in process
 
 
Q