-1

Since the latest xcode update (to version 12) the delegate methode didSelectItemAt of a nested UIColletionView doesn't respond.

My structure: UITableView (vertical) - UITableViewCell - UICollectionView (horizontal)

The vertical tableview consists of three sections. Two section have only one tableViewCell each. Each of these tableViewCells have a horizontal collectionView. the last section has more tableViewCells.

i'm using the tableViews didSelectRowAt method only for the third section. For section 1 and 2 i'm using the collectionViews didSelectItemAt and sending a callback via tableViewCell. but the didSelectItemAt doesn't respond to users tap.

I do not use a custom select method.

Before the update to xcode 12 (swift 5.3) everything works as expected.

Code:

private lazy var tableView: UITableView = {
    let tv = UITableView(frame: CGRect.zero, style: .grouped)
    
    tv.translatesAutoresizingMaskIntoConstraints = false
    tv.delegate = self
    tv.dataSource = self
    
    tv.register(FirstHeader.self, forHeaderFooterViewReuseIdentifier: FirstHeader.reuseIdentifier)
    tv.register(SecondHeader.self, forHeaderFooterViewReuseIdentifier: SecondHeader.reuseIdentifier)
    tv.register(FirstTVCell.self, forCellReuseIdentifier: FirstTVCell.reuseIdentifier)
    tv.register(SecondTVCell.self, forCellReuseIdentifier: SecondTVCell.reuseIdentifier)
    tv.register(ThirdTVCell.self, forCellReuseIdentifier: ThirdTVCell.reuseIdentifier)
    
    
    tv.alwaysBounceVertical = true
    tv.isDirectionalLockEnabled = true
    
    return tv
}()

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch indexPath.section {
    case 1:
        guard let cell = tableView.dequeueReusableCell(withIdentifier: FirstTVCell.reuseIdentifier) as? FirstTVCell else { fatalError("Cant dequeue FirstTVCell") }
        
        cell.setup(elements: firstElements, didSelect: onTap)
        cell.selectionStyle = .none
        
        return cell
    case 2:...
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    switch indexPath.section {
    case 3:
        onCellTap?(thirdElements?[indexPath.row])
    default:
        return
    }
}

Code of tableViewCell with collectionView

class FirstTVCell: UITableViewCell {

static let reuseIdentifier = "FirstTVCell"
private var didSelect: ((Element?) -> Void)?
private var elements: [Element]?

private lazy var collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
    
    cv.translatesAutoresizingMaskIntoConstraints = false
    
    cv.delegate = self
    cv.dataSource = self
    
    cv.register(ChipCell.self, forCellWithReuseIdentifier: ChipCell.reuseIdentifier)
    
    return cv
}()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: .default, reuseIdentifier: reuseIdentifier)
    addSubview(collectionView)
    
    NSLayoutConstraint.activate([
        collectionView.centerYAnchor.constraint(equalTo: centerYAnchor),
        collectionView.centerXAnchor.constraint(equalTo: centerXAnchor),
        collectionView.widthAnchor.constraint(equalTo: widthAnchor),
        collectionView.heightAnchor.constraint(equalTo: heightAnchor)
    ])
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func setup(elements: [CoreElement]?, didSelect: ((CoreElement?) -> Void)?) {
    self.didSelect = didSelect
    self.elements = elements
    collectionView.reloadData()
}}
extension ListChipCollectionCell: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
...

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    didSelect?(elements?[indexPath.row])
}}

CollectionViewCell

class ChipCell: UICollectionViewCell {

static let reuseIdentifier = "ChipCell"

private let titleLabel: UILabel = {
    let l = UILabel()
    
    l.translatesAutoresizingMaskIntoConstraints = false
    l.font = .customFont(of: .semiBold, size: 14)
    l.textAlignment = .center
    l.numberOfLines = 1
    
    return l
}()

func setup(element: CoreElement?) {
    titleLabel.text = element?.title
    addSubview(titleLabel)
    
    NSLayoutConstraint.activate([
        
        titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
        titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
        titleLabel.widthAnchor.constraint(equalTo: widthAnchor, constant: -20)
    ])
}

}

andre_hold
  • 562
  • 8
  • 20
  • Add the relevant code. – PGDev Sep 23 '20 at 13:19
  • @PGDev code is added. – andre_hold Sep 23 '20 at 14:08
  • @andre_hold - what is `bgView` in your `ChipCell` class? – DonMag Sep 23 '20 at 17:04
  • @DonMag its another view. I‘ve shorten the code snippet. I’m going to remove this in the post – andre_hold Sep 23 '20 at 19:35
  • 1
    @andre_hold - Tip: it's very difficult to fix code when the question shows *sort of like my code*. Based on what you've shown, I suspect the problem is that in both your `UITableViewCell` and `UICollectionViewCell` classes, it looks like you are adding subviews directly to the cell itself. That's a no-no. You should be adding subviews to the cells' built-in `.contentView`. – DonMag Sep 23 '20 at 19:49
  • @DonMag it was the ``.contentView``. thank you – andre_hold Sep 24 '20 at 06:52

2 Answers2

0

Thanks to the comment of @DonMag i've forgot to add the views in each UITableViewCell and UICollectionViewCell to their .contentView.

Instead of addSubview(collectionView) using contentView.addSubview(collectionView) on UITableViewCell

Before

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: .default, reuseIdentifier: reuseIdentifier)
    
    backgroundColor = .black
    addSubview(collectionView)
    
    NSLayoutConstraint.activate([
        collectionView.centerYAnchor.constraint(equalTo: centerYAnchor),
        collectionView.centerXAnchor.constraint(equalTo: centerXAnchor),
        collectionView.widthAnchor.constraint(equalTo: widthAnchor),
        collectionView.heightAnchor.constraint(equalTo: heightAnchor)
    ])
}

After

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: .default, reuseIdentifier: reuseIdentifier)
    
    backgroundColor = .black
    contentView.addSubview(collectionView)
    
    NSLayoutConstraint.activate([
        collectionView.centerYAnchor.constraint(equalTo: centerYAnchor),
        collectionView.centerXAnchor.constraint(equalTo: centerXAnchor),
        collectionView.widthAnchor.constraint(equalTo: widthAnchor),
        collectionView.heightAnchor.constraint(equalTo: heightAnchor)
    ])
}
andre_hold
  • 562
  • 8
  • 20
0

If you are using addSubview in cell, you need to do the follow:

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    contentView.isUserInteractionEnabled = true
}
Ihor Chernysh
  • 446
  • 4
  • 5