UICollectionViewCell与其UICollectionViewController交谈

时间:2018-04-26 09:37:36

标签: ios swift uicollectionview delegates uicollectionviewcell

虽然可能具有主观性,但我想知道如何设置自定义UICollectionViewCell,当按下UIButton时,会通知自定义UICollectionViewController该怎么做。

我的第一个想法是使用delegate中的CustomCell,如下所示:

class CustomCell: UICollectionViewCell {

    var delegate: CustomCellDelegate?

    static let reuseIdentifier = "CustomCell"

    @IBOutlet weak private var button: UIButton! {
        didSet {
            button.addTarget(self, action: #selector(self.toggleButton), for: .touchUpInside)
        }
    }

    @objc private func toggleButton() {
        delegate?.didToggleButton()
    }

}

CustomCellDelegate的类协议定义为:

protocol CustomCellDelegate: class {
    func didToggleButton()
}

UICollectionViewController然后实现didToggleButton函数并将自己指定为每个单元格的delegate,如下所示:

class CustomCollectionViewController: UICollectionViewController, CustomCellDelegate {

    func didToggleButton() {
        // do some stuff and then update the cells accordingly ...
        collectionView?.reloadData()
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let customCell = collectionView.dequeueReusableCell(withReuseIdentifier: CustomCell.reuseIdentifier, for: indexPath) as? CustomCell else { fatalError("Unexpected indexPath") }
        customCell.delegate = self
        return customCell
    }
}

这是解决这个问题的正确方法,还是有另一种方式在UICollectionViewCell和它的父控制器之间进行通信?

感谢您的任何建议。

2 个答案:

答案 0 :(得分:1)

是的,这是正确的解决方案。您的自定义单元格是盲目的,他们对您的控制器一无所知。他们只启动委托方法。

但是,还有一个正确的解决方案和它的观察结果。有人更喜欢委托,有人更喜欢观察。您可以使用NotificationCenter发布有关单元格中发生的触摸的通知,并使控制器成为对这些通知做出反应的观察者。

// inside your cell
NotificationCenter.default.post(name: Notification.Name("ButtonPressed"), object: nil)

// inside your controller
NotificationCenter.default.addObserver(self, selector: #selector(someHandler), name: Notification.Name("ButtonPressed"), object: nil)

当您的控制器(观察者)捕获已发布的事件时,您的func someHandler()将处理该调用。

此外,还有 KVO ,但由于您有多个单元格,所以它很乱并且不适合这种情况。

设置通信渠道的另一种方法是绑定。它可以手动编写或反应(例如,使用ReactiveSwift)。

例如,手动一个:

// in your controller 
cell.pressHandler = {
    // do something
    ...
}

// in your cell
var pressHandler: (() -> Void)?

...

// when the button is pressed you execute that handler
pressHandler?()

答案 1 :(得分:0)

是的,当只需要对一个对象进行通信时,委派是最佳的。在这种情况下,父UICollectionViewController

其他通讯方法是 -

通知:当我们想要在通知后传达多个对象时。

KVO:知道值/属性何时发生变化。但要小心使用。