【问题标题】:UICollectionViewCell Talking to Its UICollectionViewControllerUICollectionViewCell 与它的 UICollectionViewController 对话
【发布时间】:2018-04-26 09:37:36
【问题描述】:

尽管可能是主观的,但我想知道如何使用自定义UICollectionViewCell,当按下它的UIButton 时,会通知自定义UICollectionViewController 要做什么。

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

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 与其父控制器之间进行通信?

感谢您的任何建议。

【问题讨论】:

  • 也许是这样。委派是一种正统的方法,可以很好地实现效果。你也可以使用binding
  • @Nitish 感谢您的 cmets ...

标签: ios swift uicollectionview delegates uicollectionviewcell


【解决方案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?()

【讨论】:

  • 在这种情况下我永远不会去通知中心。一方面,它是一对多的通信,另一方面,它会导致糟糕的架构。
  • 就个人而言,我也认为委托在这里更好,在我的项目中我总是做委托:)
  • 我在答案中又添加了一个选项。
  • @Aleksandr-Honcharov 谢谢你们两位的cmets——他们澄清了我的担忧......
【解决方案2】:

是的,当只能对一个对象进行通信时,委托是最佳选择。在这种情况下,父 UICollectionViewController

其他沟通方式是-

通知:当我们要沟通多个对象时发布通知。

KVO:知道值/属性何时发生变化。但请谨慎使用。

【讨论】:

  • 在这种情况下我永远不会去通知中心。一方面它是一对多的通信,另一方面它会导致糟糕的架构
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多