SwiftyJD
SwiftyJD

Reputation: 5441

Perform a segue selection from a uicollectionview that is embedded in a tableview cell?

Currently we have a uicollectionview that is embedded in a tableview cell. When the collection view cell is selected it's suppose to initiate a push segue to another view controller. The problem is there is no option to perform the segue on the cell. Is there a way around it? Here is the cell:

class CastCell : UITableViewCell {

  var castPhotosArray: [CastData] = []

  let extraImageReuseIdentifier = "castCollectCell"
  let detailToPeopleSegueIdentifier = "detailToPeopleSegue"

  var castID: NSNumber?

  @IBOutlet weak var castCollectiontView: UICollectionView!

  override func awakeFromNib() {
    castCollectiontView.delegate = self
    castCollectiontView.dataSource = self
  }
}


extension CastCell: UICollectionViewDataSource {

  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return castPhotosArray.count
  }

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = castCollectiontView.dequeueReusableCell(withReuseIdentifier: extraImageReuseIdentifier, for: indexPath) as! CastCollectionViewCell

    cell.actorName.text = castPhotosArray[indexPath.row].name     
    return cell
  }
}

extension CastCell: UICollectionViewDelegate {

     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
      self.castID = castPhotosArray[indexPath.row].id

     performSegue(withIdentifier: detailToPeopleSegueIdentifier, sender: self) //Use of unresolved identifier 'performSegue' error

    }
}


extension CastCell {
   func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let peopleVC = segue.destination as! PeopleDetailViewController

    peopleVC.id = self.castID
  }
}

Upvotes: 1

Views: 487

Answers (2)

matt
matt

Reputation: 534977

The problem is there is no option to perform the segue on the cell

There is no such thing as a "segue on a cell". A segue is from one view controller to another. performSegue is a UIViewController method. So you cannot say performSegue from within your CastCell class, because that means self.performSegue, and self is a UITableViewCell — which has no performSegue method.

The solution, therefore, is to get yourself a reference to the view controller that controls this scene, and call performSegue on that.

In a situation like yours, the way I like to get this reference is by walking up the responder chain. Thus:

var r : UIResponder! = self
repeat { r = r.next } while !(r is UIViewController)
(r as! UIViewController).performSegue(
    withIdentifier: detailToPeopleSegueIdentifier, sender: self)

Upvotes: 3

user5890979
user5890979

Reputation:

1: A clean method is to create a delegate protocol inside your UITableViewCell class and set the UIViewController as the responder.

2: Once UICollectionViewCell gets tapped, handle the taps inside the UITableViewCell and forward the tap to your UIViewController responder through delegatation.

3: Inside your UIViewController, you can act on the tap and perform/push/present whatever you want from there.

You want your UIViewController to know what is happening, and not call push/presents from "invisible" subclasses that should not handle those methods.

This way, you can also use the delegate protocol for future and other methods that you need to forward to your UIViewController if needed, clean and easy.

Upvotes: 1

Related Questions