У меня есть контроллер представления с представлением контейнера, в которое встроен контроллер панели вкладок. Я использую это для отображения 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])
}
До сих пор я пытался поместить функцию выполнения в функцию действия, связанную с сегментированным элементом управления. Однако это не работает, потому что, по сути, программно добавляется еще одна встроенная панель вкладок или снова вызывается переход встраивания, и я получаю это сообщение об ошибке: «В представлении контейнера есть неожиданные подпредставления. Возможно, переход встраивания уже запущен один раз или подвид был добавлен программно?"
* Закомментированные строки кода показывают, что я пробовал, но что не сработало, и где я нахожусь.
Вы не можете делать то, что пытаетесь сделать.
При встроенных переходах переход срабатывает при первой загрузке контроллера представления хоста. Это вызывает ваш метод prepare(for:sender)
один и только один раз перед загрузкой представлений встроенного контроллера представления. Больше не звонят.
Что вам нужно сделать, так это сохранить указатель на ваш дочерний контроллер представления в переменной экземпляра. Определите протокол, который родитель использует для общения с дочерним элементом, а затем используйте этот протокол для отправки сообщения дочернему элементу, когда пользователь выбирает другой сегмент в вашем сегментированном элементе управления.
Затем дочерний элемент (предположительно, контроллер панели вкладок) может переключать выбранные вкладки в ответ на определенное вами сообщение.
Насколько я могу судить, человек в ответе, которому вы следовали, давал плохой совет. Возможно, вы сможете изменить контроллер представления исходный, который отображается в контроллере панели вкладок. (Я никогда не пробовал это, но думаю, это сработает.) Дело в том, что prepare(for:sender)
вызывается один и только один раз для каждого перехода встраивания или другого перехода.
«Что вам нужно сделать, так это сохранить указатель на ваш дочерний контроллер представления в переменной экземпляра». О, я не думаю, что это очень хороший совет. У вас уже есть такой указатель; это ваш children[0]
. Определение другого указателя — хороший способ все испортить.
спасибо за ответ. Я понял, что я делал неправильно, благодаря вашим комментариям. Его программа была другой, как и его цель. Я следил за начальной настройкой, основанной на нажатии кнопки (я полагаю), тогда как мне нужен был регулируемый метод. Спасибо, что помогли мне понять. Я проголосовал, но у меня нет репутации, и это не показывает извините.
Если я ответил на ваш вопрос, вы должны принять мой ответ. Что вы МОЖЕТЕ сделать с низкой репутацией. Вам нужно всего около 16 очков репутации, чтобы проголосовать, так что вы сможете сделать это в ближайшее время.
Когда вы встраиваете контроллер представления в представление контейнера из другого контроллера представления (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 Да, вы можете использовать. Но я использовал его, потому что не знаю, есть ли у вас какой-либо другой дочерний контроллер представления в MainVC или нет. Но проверять $0 is UITabBarController
безопаснее
Попался, спасибо, да, у меня есть только tabBarController как дочерний элемент для основного, а затем три дочерних элемента для tabBarController.
Извините, я новичок в Swift и немного запутался. Что человек в ответе, за которым я следил, говорил об использовании оператора подготовки для переключения вкладки? Кроме того, исходя из того, что вы говорите, будет ли это работать, как в моей функции действия для сегментированного элемента управления, например: pointer.tabcontroller.selectedIndex = toggle.selectedSegmentIndex? Будет ли это работать как протокол, который вы описываете? (указатель - это переменная, используемая для описания дочернего контроллера представления)