Цепочка ответчика, но НЕ делегирующее свойство передает значение обратно в контроллер просмотра из контейнера

В следующем коде должны быть показаны два способа передачи информации из встроенного контроллера (UICollectionView) обратно в контроллер подробного представления с использованием подхода цепочки ответчика ИЛИ делегата. Оба подхода используют один и тот же протокол и метод делегата. Единственное отличие состоит в том, что если я закомментирую строку делегата?.method в пути didSelectItemAtIndex, цепочка респондента будет работать. НО, если я закомментирую строку цепочки респондента в методе didSelectItemAtIndex, то незарегистрированный делегат? Свойство не вызывает метод и остается нулевым.

Протокол определен и включен выше DetailViewController. Необходим для обоих подходов.

protocol FeatureImageController: class {
func featureImageSelected(indexPath: NSIndexPath)
}

Свойство делегата, объявленное в пользовательском классе UICollectionViewController, которое необходимо только для подхода делегата.

class PhotoCollectionVC: UICollectionViewController
{
   weak var delegate: FeatureImageController?

В DetailViewController создается экземпляр PhotoCollectionVC(), а для свойства делегата устанавливается значение self с протоколом делегата в качестве типа.

class DetailViewController: UIViewController, FeatureImageController 
{...
    override func viewDidLoad() {
    super.viewDidLoad()

    let photoCollectionVC = PhotoCollectionVC()
    photoCollectionVC.delegate = self as FeatureImageController

В методе didSelectItemAtIndexPath контроллера представления коллекции передайте обратно выбранный indexPath через цепочку респондента (закомментировано) ИЛИ делегат методу featureImageSelected в DetailVC.

override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
//    if let imageSelector =  targetForAction("featureImageSelected:", withSender: self) as? FeatureImageController {
//       imageSelector.featureImageSelected(indexPath)
//      }
        self.delegate?.featureImageSelected(indexPath)
}

Экземпляр элегантного метода в DetailViewController. Необходим для обоих.

func featureImageSelected(indexPath: NSIndexPath) {
    record?.featureImage = record?.images[indexPath.row]
    self.configureView()
}

Почему подход цепочки ответчика работает, а делегат - нет?

Нет ошибок компилятора или времени выполнения. В методе didSelectItemAtIndexPath делегат всегда возвращает nil, и из метода делегата ничего не печатается.

2 ответа

Решение

Ошибка в вопросе заключается в том, где в соответствующем классе "создается экземпляр PhotoCollectionVC(), а для свойства делегата устанавливается значение self". В viewDidLoad это просто создает другой экземпляр с нерелевантным свойством делегата, которое никогда не будет вызываться. Свойство делегата фактического встроенного PhotoCollectionVC должно быть присвоено self - для того, чтобы два VC могли обмениваться данными. Это делается из метода prepareForSegue:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
    ...
        let controller =  (segue.destinationViewController as! PhotoCollectionVC)
        ...
        controller.delegate = self
        }
    }
}

Остальной пример кода в порядке.

Вот очень простой пример делегирования из встроенного контейнера в его делегированный VC. Встроенный контейнер просто сообщает ВК, что кнопка была нажата. Доска объявлений - это просто ВК с контейнером и текстовым выпуском. В контейнере ВК есть только кнопка. И у segue есть идентификатор.

Код в делегате ViewController:

protocol ChangeLabelText: class
{
  func changeText()
}

class ViewController: UIViewController, ChangeLabelText
{
    @IBOutlet weak var myLabel: UILabel!

    override func viewDidLoad()
    {
        super.viewDidLoad()
        myLabel?.text = "Start"
    }

    func changeText()
    {
        myLabel?.text = "End"
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "feelTheBern"
        {
            let secondVC: myViewController = segue.destinationViewController as! myViewController
            secondVC.delegate = self
        }}
}

Код в делегирующем контроллере представления myViewController:

class myViewController: UIViewController
{
    weak var delegate: ChangeLabelText?

    @IBAction func myButton(sender: AnyObject)
    {
        print("action")
        delegate?.changeText()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Ваш код респондента вызывает функцию FeatureImageSelected для себя:

self.featureImageSelected(indexPath)

но код делегата вызывает функцию featureImageSelected для делегата:

self.delegate.featureImageSelected(indexPath)

Который будет делегатом DetailVC, а не делегатом collectionViews. Я не совсем уверен, что делает ваш код, но вы, вероятно, хотите что-то вроде

collectionView.delegate?.featureImageSelected(IndexPath)

который выглядит так, как будто бы

self.featureImageSelected(indexPath)
Другие вопросы по тегам