Swift 3-如何在UICollectionViewCell中获取按钮

我正在尝试在单元格中实现“编辑”按钮。

请参考图片:
在此处输入图像描述

到目前为止我做了什么:

MainController:

class MainController: UICollectionViewController, UICollectionViewDelegateFlowLayout { let imgCellId = "imgCellId" override func viewDidLoad() { collectionView?.backgroundColor = .white collectionView?.register(ImgItemCell.self, forCellWithReuseIdentifier: imgCellId) } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: imgCellId, for: indexPath) as! ImgItemCell cell.editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) return cell } func buttonPressed(){ print("buttonPressed !") } } 

ImgItemCell:

 import Material class ImgItemCell: UICollectionViewCell{ override init(frame: CGRect){ super.init(frame: frame) setupViews() } ... let editButton: RaisedButton = { let button = RaisedButton(title: "Edit", titleColor: .black) return button }() func setupViews(){ ... addSubview(editButton) ... } } 

结果:该按钮无法点击。 单击按钮时不会打印日志。

在android中,我通过按钮的OnClickListener完成此OnClickListener ,以执行每行的操作。 我怎样才能在Swift 3中做同样的事情?

解决方案:(这对我有用)

大家好,谢谢你的所有建议,他们更不用说我来解决问题了。

我的问题的根本原因是视图层次结构(正如@DatForis指出的那样)

说明:我想要一个单元格包含图像和按钮布局,以便我有如下的视图层次结构

 override func setupViews() { super.setupViews() addSubview(imgView) addSubview(buttonLayout) buttonLayout.addSubView(buttonList) buttonList.addSubview(editButton) buttonList.addSubview(shareButton) } 

这个层次结构以某种方式阻止了按钮的click事件。

因此,我在层次结构中改变了一点

  override func setupViews() { super.setupViews() addSubview(imgView) addSubview(buttonLayout) buttonLayout.addSubview(editButton) buttonLayout.addSubview(shareButton) } 

和BAM! 它就像一个魅力。

事实上,我需要一个正确的解释,说明层次结构对儿童的影响。

顺便说一句,我认为这里的大多数回复都是可行的解决方案,但我选择了@DonMag作为最终答案,因为它干净而清晰,对Controller有很酷的回调。

但同样,我的根本问题来自视图层次结构。

一个非常可靠和灵活的模式是为您的单元格分配一个“回调关闭”。 将您的按钮操作处理程序放在单元格中,并让它“回调”到视图控制器。

这是一个基本示例(您应该可以使用自定义单元格实现它而没有问题):

 // // CViewWithButtonCollectionViewController.swift // SWTemp2 // // Created by Don Mag on 6/5/17. // Copyright © 2017 DonMag. All rights reserved. // import UIKit private let reuseIdentifier = "ImgItemCell" class ImgItemCell: UICollectionViewCell { // this will be our "call back" action var btnTapAction : (()->())? override init(frame: CGRect){ super.init(frame: frame) setupViews() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setupViews() } let editButton: UIButton = { let button = UIButton(type: UIButtonType.system) button.translatesAutoresizingMaskIntoConstraints = false button.backgroundColor = .white button.setTitle("Edit", for: .normal) return button }() func setupViews(){ // add a button addSubview(editButton) editButton.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true editButton.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true // add the touchUpInside target editButton.addTarget(self, action: #selector(btnTapped), for: .touchUpInside) } func btnTapped() { print("Tapped!") // use our "call back" action to tell the controller the button was tapped btnTapAction?() } } class CViewWithButtonCollectionViewController: UICollectionViewController { override func viewDidLoad() { super.viewDidLoad() if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout { layout.itemSize = CGSize(width: 300, height: 100) } } override func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 10 } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! ImgItemCell cell.backgroundColor = .red // set a "Callback Closure" in the cell cell.btnTapAction = { () in print("Edit tapped in cell", indexPath) // start your edit process here... } return cell } } 

您可能希望使用标记来实现更简单的方法,但是对于单元格内的按钮,我总是实现委托模式

 protocol MyCollectionViewCellDelegate: class { func button(wasPressedOnCell cell: MyCollectionViewCell) } class MyCollectionViewCell: UICollectionViewCell { weak var delegate: MyCollectionViewCellDelegate? var data: String = "DATA" @IBAction func buttonWasPressed(sender: UIButton){ delegate?.button(wasPressedOnCell: self) } } class MainViewController: UIViewController, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "reuse", for: indexPath) as! MyCollectionViewCell cell.delegate = self return cell } } extension MainViewController: MyCollectionViewCellDelegate{ func button(wasPressedOnCell cell: MyCollectionViewCell) { //do what you want with the cell and data } } 

使用此方法将允许您在单元格内有多个按钮。 为每个按钮使用不同的委托方法

你的buttonpress方法如何知道,你正在选择哪个单元格按钮。所以你可以区分tag
添加cellForItemAtindexPath

 ButtonObject.tag = indexPath.item 

 func buttonPressed(_ sender: UIButton) { print("buttonPressed ! \(sender.tag)") } 

我创建了相同的场景。 唯一的区别是我使用了UIButton而不是RaisedButton 。 它工作得非常好。

1. ImgItemCell

 class ImgItemCell: UICollectionViewCell { //MARK: View Lifecycle Methods override func awakeFromNib() { super.awakeFromNib() setupViews() } let editButton: UIButton = { let button = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 50)) button.setTitle("Edit", for: .normal) return button }() func setupViews() { addSubview(editButton) } } 

2. MainController方法

 //MARK: UICollectionViewDataSource func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 10 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: imgCellId, for: indexPath) as! ImgItemCell cell.editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) return cell } func buttonPressed() { print("buttonPressed !") } 
 func setupViews() { ... addSubview(editButton) editButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) } func buttonPressed(sender:UIButton){ print("buttonPressed !") }