Делегирование Контроллеров Представления Контейнера - PullRequest
0 голосов
/ 19 мая 2018

У меня есть родительский viewcontroller, в котором размещены 3 контейнера viewcontroller.

В определенные моменты мне нужно передавать данные из одного контейнера viewcontroller в другой контейнер viewcontroller, и я думал, что смогу сделать это с помощью шаблона делегирования.Тем не менее, я не могу понять, почему делегат не запускается, и viewcontroller принимающего контейнера не получает никаких данных.

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

Ниже приведен сводный код по настройке:

class ParentViewController: UIViewController { 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let firstContainerVC = segue.destination as? FirstContainerVC {
            //....
        }

        if let secondContainerVC = segue.destination as? SecondContainerVC {
           //....
        }        
    }
        protocol Delegate {
           func passX(a: String?)
           func passY(b: String?)
        }
}    

class FirstContainerVC: UIViewController {

    var delegate: Delegate?

    if isTrue {
        delegate.passX(a: "TestOne")
    } else {
        delegate.passY(b: "TestTwo")
    }
}

class SecondContainerVC: UIViewController, Delegate {

    override func viewDidLoad() {
        let firstVC = self.storyboard?.instantiateViewController(withIdentifier: "firstContainer") as! FirstContainerVC
    firstVC.delegate = self
    }

    func passX(a: String?) {
        //if let a = a....
    }

    func passY(b: String?) {
        //if let b = b....
    }
}

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

К сожалению, я не знаю, как работает перетаскивание в XCode, я делаю все в коде.Однако, когда ваш родительский контроллер представления создает другой контроллер представления, просто установите родительский объект в качестве делегата контейнера.

Создайте протокол:

protocol SomeProtocol: AnyObject {
    func passX(a: String?)
    func passY(b: String?)
}

И контейнеры будут иметь делегаты типа этого протокола:

class FirstContainerVC: UIViewController {
    weak var delegate: SomeProtocol?
}

class SecondContainerVC: UIViewController {
    weak var delegate: SomeProtocol?
}

Родитель должен соответствовать протоколу, чтобы он мог стать делегатом.Затем, когда вы создаете экземпляры контейнеров (что вы должны сделать только один раз в этом сценарии), установите self в качестве их делегатов:

class ParentViewController: UIViewController, SomeProtocol {

    // make the containers instance properties so that you
    // can access them from the protocol methods
    weak var firstContainerVC = FirstContainerVC()
    weak var secondContainerVC = SecondContainerVC()

    // set the delegates at some point
    func setDelegates() {
        firstContainerVC?.delegate = self
        secondContainerVC?.delegate = self
    }

    func passX(a: String?) {
        guard let a = a else {
            return
        }
        secondContainerVC?.getFromFirst(a: a)
    }

    func passY(b: String?) {
        //
    }

}

Затем, когда вы хотите перейти от первого к второму, пройдите делегатиз первого контейнера в родительский и из родительского во второй контейнер.

class FirstContainerVC: UIViewController {

    weak var delegate: SomeProtocol?

    func sendToSecond() {
        delegate?.passX(a: "slick")
    }

}

class SecondContainerVC: UIViewController {

    weak var delegate: SomeProtocol?

    func getFromFirst(a: String) {
        print(a)
    }

}

Это несколько грубый пример.Вы должны написать свою реализацию так, как вы чувствуете себя наиболее комфортно (например, изящное развертывание, как / где вы создаете экземпляр и т. Д.).Кроме того, если все контроллеры представлений являются постоянными контроллерами представлений (это означает, что они никогда не освобождаются), нет необходимости делать их weak var.Как бы вы ни делали, концепции все одинаковы.Родитель является делегатом для контейнеров, и контейнеры взаимодействуют друг с другом через родителя.

Некоторые люди могут предложить использовать наблюдателей уведомлений или одиночные сообщения для контейнеров, чтобы общаться друг с другом, но я считаю, что этоизлишним, когда у вас есть родитель прямо там.

0 голосов
/ 19 мая 2018

Я согласен с @slickdaddy, что ваш второй контроллер представления контейнера не имеет никакого права на создание экземпляра вашего первого контроллера представления контейнера.Я подозреваю, что у вас уже был первый контейнерный VC, а теперь у вас есть 2.

Чтобы ответить на ваш вопрос о наилучшем способе передачи данных, ваши контроллеры представления контейнера не должны ничего знать о родительском контроллере представления.Посредством делегирования или обратного вызова, который регистрирует родительский объект, данные должны быть переданы родительскому элементу, а родительский элемент должен затем направить его вниз к другим заинтересованным автономным контроллерам представления.

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

Также рассмотрим другой подход: передача одного и того же объекта модели в каждый содержащийся контроллер представления.

И, наконец, мой предпочтительный подход - позволить каждому контроллеру представления (или фактически его модели представления, если выполняется MVVM) достичь одноэлементного объекта DependencyManager, в котором живут такие объекты модели.Если все сделано правильно, модульные тесты могут по-прежнему иметь полный контроль, внедряя фиктивные модели в DependencyManager.

...