I have a tableView with cells that contain UiCollectionView. My didSelect tableView’s delegate isn’t called when I touch the cell on the collectionView.
I think it’s my collectionView that get the touch instead. Do you have any elegant solution to keep the scroll enabled on my collectionView but disable the selection and pass it to the tableview ?
Here is my tableView declaration :
private lazy var tableView:UITableView = { [weak self] in
$0.register(TestTableViewCell.self, forCellReuseIdentifier: "identifier")
$0.delegate = self
$0.dataSource = self
return $0
}(UITableView())
Here are my delegate and dataSource methods:
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "identifier", for: indexPath) as! TestTableViewCell
return cell
}
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
print(indexPath)
}
And here is my cell :
public class TestTableViewCell : UITableViewCell {
private lazy var collectionViewFlowLayout:UICollectionViewFlowLayout = {
$0.scrollDirection = .horizontal
$0.minimumLineSpacing = 0
$0.minimumInteritemSpacing = 0
return $0
}(UICollectionViewFlowLayout())
private lazy var collectionView:UICollectionView = {
$0.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "identifier")
$0.delegate = self
$0.dataSource = self
return $0
}(UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowLayout))
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(collectionView)
collectionView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:UICollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: cell:"identifier", for: indexPath) as! cell:UICollectionViewCell
return cell
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return collectionView.frame.size
}
}
If you spot any compilation error, excuse me, this is an anonymized copy/past. My app is running without error.
If you want an example of what I’m trying to do you can check AirBnb’s app. TableView with some houses with cells and inside, pictures collectionView. Il you touch the collectionView, the tableView select the cell…
Thanks
3
Answers
Maybe you would like to try allowsSelection property of UICollectionView. If you set this property false, your collection view cells are not selected any more.
And I think tableView didSelect can capture user interaction. If UITableView still can not capture didSelect, you can give delegate to collectionView and fire it once it’s tapped by adding a tap gesture onto UICollectionView.
You can do the following
First in first, print something in
didSelectItem
of your collectionView delegate, to make ensure that your collectionView cell is tapped.add a delegate property in your
UICollectionViewClass
and call the delegate in theDidSelectItem
if the step 1 is performing correctly.In your UITableViewController, you have a function
cellForRowAtIndexPath
, here add the delegate property for the associate cell.If you can print something in your delegate function, then you are at your last step. Call
super.didSelect..
with your indexPath, because now you have everything to call didSelect manually.I don’t believe there is a "direct" way to do what you’re asking. The collection view will respond to the gestures, so they can’t "flow through" to the table view / cells without using a closure or protocol/delegate pattern.
Here’s one approach…
We subclass
UICollectionView
and, ontouchesBegan
call a closure to tell the table view to select the row.We can also implement
scrollViewWillBeginDragging
to select the row on collection view scroll, in addition to collection view "tap."So…
View Controller class
Table View Cell class
UICollectionView subclass
UICollectionView Cell class