这是我在创建cell时一直陷入困境的一个问题。
假设我有一个自定义单元格 (PlaceCell
),我在不同的 Controller 和 Collection View 中使用它。它有一个标签,用于标识地点名称 (PlaceNameLabel
),并且当用户点击它时将导航到地点详细信息。
这与 Controller 、 Collection View 或单元格的使用位置无关,这与其使用位置无关。
所以我必须将 PlaceNameLabel 的 UITapGestureRecognizer
代码放入 PlaceCell
类中。
class PlaceCell: UICollectionViewCell {
@IBOutlet weak var placeName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
initEventListeners()
}
func initEventListeners() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self,
action: #selector(handlePlaceNameTouch))
}
func handlePlaceNameTouch() {
// I have to push a new view controller here
}
}
但是如果我想推送地点详细 View Controller ,我需要访问该 Controller 。如果我想访问 Controller ,我有两个选择,这就是我陷入困境的地方,我读过很多SO问题的答案,其中大多数建议选择第二个选项,但我认为第一个是更好的方法。但不知道引用cell内的 Controller 是否有问题。
您能否分享一下您的意见或任何其他方法来处理这个问题?
第一个选项
引用单元内的 Controller ,
extension MyController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PlaceCell", for: indexPath) as! PlaceCell
cell.controller = self
return cell
}
}
class PlaceCell: UICollectionViewCell {
var controller: UIViewController?
@IBOutlet weak var placeName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
initEventListeners()
}
func initEventListeners() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self,
action: #selector(handlePlaceNameTouch))
}
func handlePlaceNameTouch() {
controller.navigationController.pushViewController(PlaceDetailController(),
animated: true)
}
}
第二个选项
创建协议(protocol)和委托(delegate),将事件传递给 Controller 并做任何你想做的事情, (我认为这不好,因为操作是关于单元的,并且我必须多次创建协议(protocol)函数,因为我在不同的 Controller 中使用这个单元)
protocol PlaceCellDelegate {
func handlePlaceNameTouch()
}
class PlaceCell: UICollectionViewCell {
var delegate: PlaceCellDelegate?
@IBOutlet weak var placeName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
initEventListeners()
}
func initEventListeners() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self,
action: #selector(handlePlaceNameTouch))
}
func handlePlaceNameTouch() {
delegate?.handlePlaceNameTouch()
}
}
extension MyController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, PlaceCellDelegate {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PlaceCell", for: indexPath) as! PlaceCell
cell.delegate = self
return cell
}
func handlePlaceNameTouch() {
self.navigationController.pushViewController(PlaceDetailController(), animated: true)
}
}
最佳答案
您无需专门处理单元格选择。无需使用 UITapGestureRecognizer
或无需实现您自己的协议(protocol)来检测单元格选择。
UICollectionView
和 UITableView
有自己的协议(protocol)。
UICollectionView
的单元格选择委托(delegate) - UICollectionViewDelegate
协议(protocol)
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
UITableView
的单元格选择委托(delegate) - UITableViewDelegate
协议(protocol)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
确认协议(protocol)
并在UIViewController
上设置委托(delegate)
class viewcontroller : UICollectionViewDelegate {
@IBOutlet weak collectionView: UICollectionView!
func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
}
}
并在 View Controller 内实现协议(protocol)方法,正如我上面提到的。
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//indexPath - Index path of selected cell.
// Add you cell selection logic here.
}
当您点击单元格时,将触发此方法。在此方法内,从数据源数组中获取模型。并根据用户选择的单元格(模型)导航到详细 View 。
关于ios - 如何处理 UICollectionviewCell 或 UITableViewCell 内的按钮触摸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45062590/