Возникли проблемы с «достижением» моей функции подготовки переопределения для программного изменения представлений в контроллере панели вкладок

У меня есть контроллер представления с представлением контейнера, в которое встроен контроллер панели вкладок. Я использую это для отображения 3 разных контроллеров представления в зависимости от того, что нажато из сегментированного элемента управления в основном vc. Я следую этому решению: https://stackoverflow.com/a/38283669/11536234

Моя проблема в том, что когда я меняю индекс сегментированного элемента управления (нажимая другой сегмент), я не могу понять, как «достичь» функции подготовки.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    print("prepare reached")

    //super.prepare(for: segue, sender: sender)
    //switch(segue.identifier ?? "") {
    //case "TabBar":

        guard let TabController = segue.destination as? UITabBarController else {
            fatalError("Unexpected destination: \(segue.destination)")
        }

        TabController.selectedIndex = toggle.selectedSegmentIndex

    //default:
        //fatalError("Unexpected Segue Identifier; \(segue.identifier)")
    //}
}

@IBAction func toggleAction(_ sender: UISegmentedControl) {
    print("toggle is now at index: ", toggle.selectedSegmentIndex)
    //performSegue(withIdentifier: "TabBar", sender: sender)
    //container.bringSubview(toFront: views[sender.selectedSegmentIndex])
}

До сих пор я пытался поместить функцию выполнения в функцию действия, связанную с сегментированным элементом управления. Однако это не работает, потому что, по сути, программно добавляется еще одна встроенная панель вкладок или снова вызывается переход встраивания, и я получаю это сообщение об ошибке: «В представлении контейнера есть неожиданные подпредставления. Возможно, переход встраивания уже запущен один раз или подвид был добавлен программно?"

* Закомментированные строки кода показывают, что я пробовал, но что не сработало, и где я нахожусь.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
43
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы не можете делать то, что пытаетесь сделать.

При встроенных переходах переход срабатывает при первой загрузке контроллера представления хоста. Это вызывает ваш метод prepare(for:sender) один и только один раз перед загрузкой представлений встроенного контроллера представления. Больше не звонят.

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

Затем дочерний элемент (предположительно, контроллер панели вкладок) может переключать выбранные вкладки в ответ на определенное вами сообщение.

Извините, я новичок в Swift и немного запутался. Что человек в ответе, за которым я следил, говорил об использовании оператора подготовки для переключения вкладки? Кроме того, исходя из того, что вы говорите, будет ли это работать, как в моей функции действия для сегментированного элемента управления, например: pointer.tabcontroller.selectedIndex = toggle.selectedSegmentIndex? Будет ли это работать как протокол, который вы описываете? (указатель - это переменная, используемая для описания дочернего контроллера представления)

Brahm 22.05.2019 00:20

Насколько я могу судить, человек в ответе, которому вы следовали, давал плохой совет. Возможно, вы сможете изменить контроллер представления исходный, который отображается в контроллере панели вкладок. (Я никогда не пробовал это, но думаю, это сработает.) Дело в том, что prepare(for:sender) вызывается один и только один раз для каждого перехода встраивания или другого перехода.

Duncan C 22.05.2019 01:07

«Что вам нужно сделать, так это сохранить указатель на ваш дочерний контроллер представления в переменной экземпляра». О, я не думаю, что это очень хороший совет. У вас уже есть такой указатель; это ваш children[0]. Определение другого указателя — хороший способ все испортить.

matt 22.05.2019 05:44

спасибо за ответ. Я понял, что я делал неправильно, благодаря вашим комментариям. Его программа была другой, как и его цель. Я следил за начальной настройкой, основанной на нажатии кнопки (я полагаю), тогда как мне нужен был регулируемый метод. Спасибо, что помогли мне понять. Я проголосовал, но у меня нет репутации, и это не показывает извините.

Brahm 23.05.2019 18:57

Если я ответил на ваш вопрос, вы должны принять мой ответ. Что вы МОЖЕТЕ сделать с низкой репутацией. Вам нужно всего около 16 очков репутации, чтобы проголосовать, так что вы сможете сделать это в ближайшее время.

Duncan C 23.05.2019 21:27
Ответ принят как подходящий

Когда вы встраиваете контроллер представления в представление контейнера из другого контроллера представления (MainVC), переход выполняется только один раз при загрузке MainVC. Чтобы передать значения встроенному UIViewController/UITabBarController, вам нужно получить контроллер представления ребенок и отправить данные

class MainVC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    @IBAction func segmentControlAction(_ sender: UISegmentedControl) {
        if let tabBarVC = self.children.first(where: { $0 is UITabBarController }) as? UITabBarController {
            tabBarVC.selectedIndex = sender.selectedSegmentIndex
        }
    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        //called before mainvc viewDidLoad
        let destinationVC = segue.destination as? UITabBarController
        destinationVC?.selectedIndex = 1
    }
}

Спасибо! Дункан помог мне понять, что это именно то направление, в котором мне нужно двигаться, и ваш код помог мне добраться до моего дочернего VC... просто чтобы понять, что здесь происходит: какова цель оператора $0 is UITabBarController? Кажется излишним писать это утверждение вместе с as? UITabBarController? Разве я не мог просто сделать, если пусть tabVC = self.childViewControllers[0] как? UITabBarController

Brahm 23.05.2019 19:14

@Brahm Да, вы можете использовать. Но я использовал его, потому что не знаю, есть ли у вас какой-либо другой дочерний контроллер представления в MainVC или нет. Но проверять $0 is UITabBarController безопаснее

RajeshKumar R 23.05.2019 19:30

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

Brahm 23.05.2019 19:43

Другие вопросы по теме