Home > Enterprise >  Collection view within collection view cell not allowing didSelectItemAt to be called?
Collection view within collection view cell not allowing didSelectItemAt to be called?

Time:04-28

I have a UICollectionView that appropriately recognizes taps on its cells in its collectionView(didSelectItemAt: ) delegate method.

However, I then embedded a collection view within the cell itself (so that each cell has its own collection view inside of it), but now the parent cell is not recognizing any taps anymore, I'm assuming because the embedded collection view is eating them up.

Is there some property that needs to be set so that the original (parent) cells register taps again even with their embedded collection views?

CodePudding user response:

This functionality can be confusing, as users are accustomed to "something else" happening when interacting with a control in a table view cell, rather than it selecting (or also selecting) the row itself.

However, if you really want to do that...

One approach is to use a closure in your cell. When you handle didSelectItemAt use the closure to tell the table view controller to select the row.

Note that Apple's docs point out:

Note

Selecting a row programmatically doesn't call the delegate methods tableView(_:willSelectRowAt:) or tableView(_:didSelectRowAt:), nor does it send selectionDidChangeNotification notifications to observers.

So, if you need to execute code when a table view row is selected, you'll need to call that yourself - something like this:

func myTableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print("My didSelectRowAt:", indexPath)
}

Using the code in my answer to your previous question...

In SomeTableCell add this closure setup:

public var didSelectClosure: ((UITableViewCell) ->())?

and, still in SomeTableCell:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    print("collectionView didSelecteItemAt:", indexPath)
    print("Calling closure...")
    didSelectClosure?(self)
}

Next, in cellForRowAt in the table view controller, set the closure:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "someTableCell", for: indexPath) as! SomeTableCell
    cell.rowTitleLabel.text = "Row \(indexPath.row)"
    cell.thisData = myData[indexPath.row]
    
    cell.didSelectClosure = { [weak self] c in
        guard let self = self,
              let idx = tableView.indexPath(for: c)
        else { return }
        // select the row
        tableView.selectRow(at: idx, animated: true, scrollPosition: .none)
        // that does not call didSelectRowAt, so call our own func
        //   if we want something to happen on row selection
        self.myTableView(tableView, didSelectRowAt: idx)
    }
    
    return cell
}

CodePudding user response:

you can implement UICollectionViewDataSource & UICollectionViewDelegate methods of inner collectionViews inside the cells itself & pass the events with closure to main class with main UICollectionView.

  • Related