Как избежать следа делегатских звонков - PullRequest
2 голосов
/ 15 марта 2019

У меня есть UIViewController с UICollectionView, внутри которого у меня есть ListSectionController класс, который контролирует UICollectionViewCell, а внутри этой ячейки у меня есть UIView подкласс.

Когда кнопка нажата, мне нужно вызвать метод из 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

Это похоже на многократное дублирование кода и немного пустой траты. Как я могу улучшить это?

Ответы [ 3 ]

1 голос
/ 15 марта 2019

Когда кнопка нажата, мне нужно вызвать метод из UIViewController

Один из способов: дать кнопке действие с нулевым таргетингом и реализовать действиеметод в UIViewController.Сообщение придет автоматически.

Например, мы даем кнопке действие с нулевым таргетингом:

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

А в контроллере вида у нас есть:

    @objc func buttonPressed(_ sender: Any) {

Это будет работать, потому что контроллер вида расположен вверх по цепочке респондента от кнопки.Это именно то, для чего нужны действия с нулевым таргетингом.


Другой способ - использовать NotificationCenter и Notification.Я думаю, что это вполне уместно и в этой ситуации.

0 голосов
/ 16 марта 2019

Я сталкивался с этим условием очень много раз, поэтому я хотел бы сначала указать очевидное:

"Если ваша ячейка (и взгляды внутри нее) отвечают за выполнение одного и только одного действия (может быть, этовнутри кнопки формы) ", вы можете использовать didSelectItemAtIndexPath". Создавая ваше представление с помощью UIImageView. Этот подход имеет некоторые проблемы с UX, такие как выделение и все, кроме тех, которые могут быть обработаны с делегатом.

Если это не так, и ваша клетка выполняет более одного действия, ответ Мата дает наилучшие подходы.

0 голосов
/ 15 марта 2019

Вы можете напрямую перейти по цепочке респондента к любому родительскому представлению или контроллеру представления общим безопасным способом:

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