如何避免委托调用的痕迹

How to avoid a trail of delegate calls

我有一个 UIViewController,里面有一个 UICollectionView,里面有一个 ListSectionController class,它控制 UICollectionViewCell,在那个单元格里面我有一个 UIView subclass.

按下按钮时,我需要从 UIViewController 调用一个方法。目前我有一些委托方法,因为它可以像这样返回到视图控制器:

class MyView {
    // delegate is the cell that the view is contained in

    @IBAction func buttonPress() {
        delegate?.myDelegateMethod()
    }
}

extension MyCell : MyViewDelegate {
    // The delegate is the section controller

    func myDelegateMethod() {
        delegate?.myDelegateMethod()
    }
}

... etc

这似乎有很多代码重复,有点浪费 space。我该如何改进?

您可以通过类型安全的通用方式将响应者链向上直达任何父视图或视图控制器:

extension UIResponder {
    func firstParent<T: UIResponder>(ofType type: T.Type ) -> T? {
        return next as? T ?? next.flatMap { [=10=].firstParent(ofType: type) }
    }
}
guard let ListSectionController = firstParent(ofType: ListSectionController) else {
 return // we aren't in a ListSectionController
}
//Call ListSectionController methods here

When a button is pressed I need to call a method from the UIViewController

一种方法:给按钮一个无针对性的动作并在UIViewController 中实现动作方法。消息会自动到达。

例如,我们给按钮一个 nil-targeted 动作:

    class Dummy {
        @objc func buttonPressed(_:Any) {}
    }
    button.addTarget(nil,
        action: #selector(Dummy.buttonPressed),
        for: .touchUpInside)

在视图控制器中我们有:

    @objc func buttonPressed(_ sender: Any) {

这会起作用,因为视图控制器位于按钮 响应链 的上游。这正是无目标操作的目的。


另一种方法是使用 NotificationCenter 和 Notification。我认为这也非常适合这种情况。

这种情况我已经遇到很多次了,所以我想先说明一下:

"If your cell (and views inside it) are responsible of performing one and only one action (may be that is form button inside it)",您可以使用 didSelectItemAtIndexPath”。通过使用 UIImageView 设计您的视图。这种方法有一些 UX 问题,例如突出显示,除此之外的所有问题都可以使用代表也是。

如果情况并非如此,并且您的细胞正在执行不止一项操作,Mat 的回答给出了最佳方法。