从不同于 Cell Click 的 UICollectionViewCell 按钮执行 Segue
Posted
技术标签:
【中文标题】从不同于 Cell Click 的 UICollectionViewCell 按钮执行 Segue【英文标题】:Perform Segue from UICollectionViewCell Button different from Cell Click 【发布时间】:2017-04-17 18:37:09 【问题描述】:我有一个UICollectionViewCell
,还有一个UIButton
。我有两个不同的动作。第一个,当用户按下单元格时,会用didSelectITemAt
切换到另一个视图;第二个,当用户在单元格内按下UIButton
。
我的问题是,在MyCollectionViewCell
的 Swift 代码上,我无法执行 segue,当我编写代码时:
self.performSegue(withIdentifier: "toStoreFromMyDiscounts", sender: nil)
它说错误:
MyCollectionViewCell 类型的值没有成员 performSegue。
我也不能写prepareForSegue
,它不会自动完成。
我如何从一个单元格创建一个与单击单元格本身不同的转场?
【问题讨论】:
您考虑过使用委托吗? 所以您试图从单元格以及单元格内的按钮中分离?哪个不工作? 两个我都想要,我想让他们去不同的地方。 【参考方案1】:你不能从你的UICollectionViewCell
子类中调用performSegue
,因为UICollectionViewCell
上有no interface declared 这样。
它之所以工作didSelectItemAtIndexPath()
是因为我认为你的UICollectionView
的delegate 是一个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)
【讨论】:
谢谢,我关心女巫牢房被窃听了,我该怎么办? 谢谢,马上试试!【参考方案2】:这是一个优雅的解决方案,只需要几行代码:
-
创建自定义 UICollectionViewCell 子类
使用情节提要,为按钮的“Touch Up Inside”事件定义一个 IBAction
定义闭包
从 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, e.g. call preformSegue()
self.performSegue(withIdentifier: "your segue", sender: self)
return cell
您也可以将此方法与表视图控制器一起使用。
【讨论】:
【参考方案3】:另一个也很有效的解决方案:
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)
【讨论】:
以上是关于从不同于 Cell Click 的 UICollectionViewCell 按钮执行 Segue的主要内容,如果未能解决你的问题,请参考以下文章
如何在 BitLocker 解密驱动器上从不同于 Windows 的操作系统中检索添加的文件
Eclipse J-Link ATMEL ARM ATSAME70Q21。当代码从不同于 0x00400000 的地址开始时进行调试
this.$set,或者Vue.set(),@cell-click=“cellClick“