Переключение таба
Closed this issue · 5 comments
Привет. Как через нивелир можно достать TabBar и открыть на нем второй таб?
topCotainer у меня RootViewController.
Пытаюсь найти TabBar через container, но он его не видит.
Мой код:
navigator.navigate { route in
route
.first(.tabs)
.selectTab(of: UINavigationController.self, with: .index(1))
.makeVisible()
}
Проблему обнаружил в этих строчках когда:
guard let vc = viewController?.navigationController else { return }
navigator.navigate(from: vc) {
$0.embedReplacing(makeTabsScreen())
}
Если навигировать не из navigationController, тогда все работает ок:
func setTabsScreen() async {
navigator.navigate(to: showHomeRoute())
}
func showHomeRoute() -> ScreenWindowRoute {
@IntercityInjected
var tabsScreenFactory: TabsScreenFactoryProtocol
return ScreenWindowRoute()
.setRoot(to: tabsScreenFactory.makeTabsScreen())
.makeKeyAndVisible()
}
Но проблема в том, что мне нужен navigationController в этом кейсе.
Привет 👋
Не совсем понятно, как код из второго сообщения взаимодействует с кодом из первого сообщения?
Можете еще прислать логи с ошибками?
Есть роутинг диплинка, который переключает на другой таб:
navigator.navigate { route in
route
.first(.tabs)
.selectTab(of: UINavigationController.self, with: .index(1))
.makeVisible()
}
Есть создание таб бара:
guard let vc = viewController?.navigationController else { return }
navigator.navigate(from: vc) {
$0.embedReplacing(makeTabsScreen())
}
Код embedReplacing:
func embedReplacing<New: Screen>(
_ screen: New,
animated: Bool = true,
route: (_ route: ScreenRootRoute<New.Container>) -> ScreenRouteConvertible = { $0 }
) -> Self where New.Container: UIViewController {
embedReplacing(
screen,
animated: animated,
route: route(.initial).route()
)
}
func embedReplacing<New: Nivelir.Screen, Route: ScreenThenable>(
_ screen: New,
animated: Bool = true,
route: Route
) -> Self where New.Container: UIViewController, Route.Root == New.Container {
fold(
action: ScreenEmbedReplacingAction<New, Current>(
screen: screen,
animated: animated
),
nested: route
)
}
Когда приходит диплинк и вызывается первый код для диплинки. Пишет, что контейнер TabBar не найден:
Info: Searching for a first container of UITabBarController type in UIWindow
Error: No container of UITabBarController type found for:
ScreenFirstAction<UIWindow, UITabBarController>(predicate: container of UITabBarController type)
Важно сказать, что что tabBar я кладу как child на другой viewController. Мб в этом проблема?
public func perform(
container: Container,
navigator: Nivelir.ScreenNavigator,
completion: @escaping Completion
) {
navigator.logInfo("EmbedReplacing \(screen) on \(type(of: container))")
let child = screen.build(navigator: navigator)
// TODO: - Разобраться с ошибкой
guard let parent = container.parent else {
completion(.failure(NSError(domain: "", code: 999)))
return
}
container.willMove(toParent: nil)
container.view.removeFromSuperview()
container.removeFromParent()
container.didMove(toParent: nil)
parent.addChildController(child)
completion(.success(child))
}
Скорее всего да, проблема из-за встраивания, нивелир по умолчанию не ищет кастомный контейнер в children
.
Чтобы он начал там искал, нужно подписать ViewController, в который встраивается TabBarController, под протокол ScreenIterableContainer
:
extension SomeViewController: ScreenIterableContainer {
public var nestedContainers: [ScreenContainer] {
children
}
}
Но хочется понять, какую проблему вы решаете, встраивая UITabBarController в другой контроллер? Возможно через средства Nivelir эту проблему можно решить и без встраивания.
Да, это решение помогло. Спасибо!