首页 > 解决方案 > How to make delegate between a cell with a UIView and a view controller?

问题描述

I have a view controller which holds a tableview. Inside that tableview I have a dynamic cell. Inside of that cell I have a UIView. Inside the UIView I have a label with a tap recognizer which is supposed to perform a segue to a different view controller. I have tried making a delegate between the view controller by putting vc.delegate = self in the viewdidload, but it did not work. I have also tried putting the same line inside cellforrowat, but it still doesn't do anything. How can I make a delegate that communicates from my cell with UIView to this view controller? Also, the thing that will be communicating is my UIView class and not my cell class.

标签: swift

解决方案


If I understand it correctly. Create a delegate protocol for your cell view, put delegate property to the cell and pass it via the tableView method tableView(_:cellForRowAt:) to the controller.

Protocol implementation:

protocol MyCellViewDelegate: class {
    func viewDidTap(_ view: MyCellView)
}

Cell View Implementaiton:

class MyCellView: UIView {

    private let tapGesture = UITapGestureRecognizer()
    weak var delegate: MyCellViewDelegate?
        
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        tapGesture.addTarget(self, action: #selector (viewDidTap))
    }
    
    @objc
    func viewDidTap() {
        delegate?.viewDidTap(self)
    }
}

Cell Implementation:

Then, in your Cell implementation. Pass the delegate reference to the MyCellView, which will be handled in the Controller.

class MyCell: UITableViewCell {
    
    private let myContentView = MyCellView()
    
    weak var delegate: MyCellViewDelegate? {
        didSet { myContentView.delegate = delegate }
    }
    
    required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }
}

Then you should be able to set delegate in the TableView DataSource delegate methods.

Controller Implementation:

extension MyController: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // Dequeue the cell...
        cell.delegate = self
        return cell
    }
}

And it will force you to add delegates.

extension MyController: MyCellViewDelegate {
    
    func viewDidTap(_ view: MyCellView) {
        // Do some stuff
    }
}

However, TableView could "steal" your Tap Gesture action. Maybe, if you set tableView.isUserInteractionEnabled = false, it could work.


推荐阅读