UICollectionViewCell говорит со своим UICollectionViewController - PullRequest
0 голосов
/ 26 апреля 2018

Хотя это потенциально субъективно, мне было интересно, как использовать пользовательский 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 голосов
/ 26 апреля 2018

Да, это верное решение наверняка. Ваши пользовательские ячейки слепы и ничего не знают о вашем контроллере. Они только запускают методы делегата.

Но есть еще одно правильное решение, и это наблюдение. Кто-то предпочитает делегирование, кто-то предпочитает наблюдение. Вы можете использовать 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?()
0 голосов
/ 26 апреля 2018

Да, делегирование является оптимальным, когда необходимо установить связь только с одним объектом. В этом случае родитель UICollectionViewController

Другие способы связи -

Уведомление. Когда мы хотим общаться несколькими объектами, публикуем уведомление.

KVO: знать, когда значение / свойство изменилось. Но используйте осторожно.

...