从UICollectionViewCell按钮执行Segue不同于Cell Click

我有一个UICollectionViewCell ,带有UIButton 。 我有两个不同的行动。 第一个,当用户按下单元格时,它将使用didSelectITemAt进入另一个视图; 第二个,当用户按下单元格内的UIButton
我的问题是,在Swift Code of MyCollectionViewCell ,我无法执行segue,当我编写代码时:

 self.performSegue(withIdentifier: "toStoreFromMyDiscounts", sender: nil) 

它说错误:

类型MyCollectionViewCell的值没有成员performSegue。

我也不能写prepareForSegue ,它不会自动完成。

如何从单元格创建segue,这与单击单元格本身不同?

你不能从你的UICollectionViewCell子类调用performSegue ,因为在UICollectionViewCellUICollectionViewCell像这样声明的接口 。

它工作的原因是didSelectItemAtIndexPath()是因为我认为你的UICollectionView的委托是一个UIViewController子类,有什么函数叫做performSegueWithIdentifier :()` 。

您需要在UICollectionViewCell中单击按钮时通知您的UIViewController ,以获得各种可能性,例如KVO或使用委托。

这是一个小代码片段,如何使用KVO。 这个解决方案很棒,只要你不在乎,按下按钮的单元格。

 import UIKit class CollectionViewCell: UICollectionViewCell { @IBOutlet weak var button: UIButton! } class CollectionViewController: UIViewController { @IBOutlet weak var collectionView: UICollectionView! } extension CollectionViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 1 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell: CollectionViewCell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell // Add your `UIViewController` subclass, `CollectionViewController`, as the target of the button // Check out the documentation of addTarget(:) https://developer.apple.com/reference/uikit/uicontrol/1618259-addtarget cell.button.addTarget(self, action: #selector(buttonTappedInCollectionViewCell), for: .touchUpInside) return cell } func buttonTappedInCollectionViewCell(sender: UIButton) { self.performSegue(withIdentifier: "toStoreFromMyDiscounts", sender: nil) } } 

编辑:如果您关心,触摸事件发生在哪个单元格中,请使用委托模式。

 import UIKit protocol CollectionViewCellDelegate: class { // Declare a delegate function holding a reference to `UICollectionViewCell` instance func collectionViewCell(_ cell: UICollectionViewCell, buttonTapped: UIButton) } class CollectionViewCell: UICollectionViewCell { @IBOutlet weak var button: UIButton! // Add a delegate property to your UICollectionViewCell subclass weak var delegate: CollectionViewCellDelegate? @IBAction func buttonTapped(sender: UIButton) { // Add the resposibility of detecting the button touch to the cell, and call the delegate when it is tapped adding `self` as the `UICollectionViewCell` self.delegate?.collectionViewCell(self, buttonTapped: button) } } class CollectionViewController: UIViewController { @IBOutlet weak var collectionView: UICollectionView! } extension CollectionViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 1 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell: CollectionViewCell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell // Asssign the delegate to the viewController cell.delegate = self return cell } } // Make `CollectionViewController` confrom to the delegate extension CollectionViewController: CollectionViewCellDelegate { func collectionViewCell(_ cell: UICollectionViewCell, buttonTapped: UIButton) { // You have the cell where the touch event happend, you can get the indexPath like the below let indexPath = self.collectionView.indexPath(for: cell) // Call `performSegue` self.performSegue(withIdentifier: "toStoreFromMyDiscounts", sender: nil) } } 

另一种解决方案也像魅力一样:

 extension YOURViewController : UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YOURCell", for: indexPath) as! YOURCollectionViewCell cell.butTapped = { [weak self] (YOURCollectionViewCell) -> Void in // do your actions when button tapped } } return cell } class YOURCollectionViewCell: UICollectionViewCell { var butQRTapped: ((YOURCollectionViewCell) -> Void)? @IBAction func deleteButtonTapped(_ sender: AnyObject) { butTapped?(self) } } 

这是一个优雅的解决方案,只需要几行代码:

  1. 创建自定义UICollectionViewCell子类
  2. 使用故事板,为按钮的“ Touch Up Inside ”事件定义IBAction
  3. 定义一个闭包
  4. 从IBAction打电话给关闭

Swift 4+代码

 class MyCustomCell: UICollectionViewCell { static let reuseIdentifier = "MyCustomCell" @IBAction func onAddToCartPressed(_ sender: Any) { addButtonTapAction?() } var addButtonTapAction : (()->())? } 

接下来,在你的闭包中实现你想要执行的逻辑

 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCustomCell.reuseIdentifier, for: indexPath) as? MyCustomCell else { fatalError("Unexpected Index Path") } // Configure the cell // ... cell.addButtonTapAction = { // implement your logic here, eg call preformSegue() self.performSegue(withIdentifier: "your segue", sender: self) } return cell } 

您也可以使用此方法与表视图控制器。