[英]Back button not being called in TabbarCoordinator in horizontal flow iOS 12
Coordinator pattern is an old topic with many libraries trying to solve it and I am learning it in simple example app.协调器模式是一个古老的话题,许多库试图解决它,我正在简单的示例应用程序中学习它。 My current set up is 3 rootViewControlers: LoadingStateCoordinator
, WelcomeCoordinator
, TabBarCoordinator
but missing connection between UIKit and coordinators.我当前的设置是 3 个 rootViewControlers: LoadingStateCoordinator
、 WelcomeCoordinator
、 TabBarCoordinator
但缺少 UIKit 和协调器之间的连接。 I am trying to implement it with a UINavigationController but the button is not being called.我正在尝试使用 UINavigationController 来实现它,但没有调用该按钮。 I need a way to connect to back button and a reusable coordinator that I could push to and dellocate accordingly (that is without RxSwift).*Set up Welcome screen as the parent/main navigation and always be able to come back to it.** So after user selects a form from modal view (vertical flow) presented I show on a push a TabBarCoordinator (horizontal).我需要一种连接到后退按钮的方法和一个可重用的协调器,我可以将其推送到并相应地解除分配(即没有 RxSwift)。*将欢迎屏幕设置为父/主导航,并且始终能够返回它。* * 因此,在用户从显示的模态视图(垂直流)中选择一个表单后,我会在推送时显示一个 TabBarCoordinator(水平)。 All viewControllers have empty .storyboard
, UIViewController and Coordinator exept the TabBar.Here I only have a coordinator due to the set up of child tab coordinators and the magic needs to happen on a back button tap.所有的 viewController 都有空的.storyboard
, UIViewController 和 Coordinator 除了 TabBar。这里我只有一个协调器,因为设置了子选项卡协调器,并且需要在后退按钮点击时发生魔法。 Currenly this only being called when user comes from LoadingStateCoordinator.目前只有当用户来自 LoadingStateCoordinator 时才会调用它。 There I need to send the user back to the Welcome screen so they can change the onboarding set up.在那里我需要将用户发送回欢迎屏幕,以便他们可以更改入职设置。 Here is the first code for LoadingStateCoordinator:这是 LoadingStateCoordinator 的第一个代码:
final class LoadingStateCoordinator: NSObject, Coordinator {
*// MARK: - Inputs required*
var childCoordinators: [Coordinator]
var presenter: UINavigationController
private let window: UIWindow
*// MARK: - Initialization*
init(window: UIWindow) {
self.window = window
childCoordinators = []
presenter = UINavigationController()
}
*// MARK: - Coordinator*
func start() {
let controller: LoadingStateViewController = LoadingStateViewController.instantiate()
window.rootViewController = controller
controller.delegate = self
}
}
*// MARK: - LoadingViewControllerDelegate*
extension LoadingStateCoordinator : LoadingViewControllerDelegate {
func performScreenSwitch() {
if UserDefaults.standard.userWasHere == false {
let tabCoordinator: TabBarCoordinator = TabBarCoordinator(window: window, tabBarController: UITabBarController())
window.rootViewController = presenter
addChildCoordinator(tabCoordinator)
tabCoordinator.start()
presenter.pushViewController(tabCoordinator.tabBarController!, animated: true)
} else {
let welcomeCoordinator = WelcomeCoordinator(window: window, presenter: presenter)
window.rootViewController = welcomeCoordinator.presenter
addChildCoordinator(welcomeCoordinator)
welcomeCoordinator.start()
}
}
}
And here is the TabBarCoordinator that need to perform back to Welcome screen action.这是需要执行返回欢迎屏幕操作的 TabBarCoordinator。 When I present popToRoot
function it pushes the Welcome screen but all the button there are disbled.当我展示popToRoot
功能时,它会推送欢迎屏幕,但那里的所有按钮都被禁用。 I guess to be retain cycle issue.我猜是保留周期问题。 Do I need funadametally another set up?我需要另一种设置吗? Is there a way to popToRoot(vc) in this set up?有没有办法在这个设置中 popToRoot(vc) ? What I tryed ended with runtime error "poping to non existing controller".我尝试以运行时错误“弹出到非现有控制器”结束。 TabBarCoordinator code that need to perform this:需要执行此操作的 TabBarCoordinator 代码:
final class TabBarCoordinator: NSObject, Coordinator {
internal var presenter: UINavigationController
internal var tabBarController: UITabBarController?
internal var childCoordinators: [Coordinator]
var parentCoordinator: LoadingStateCoordinator?
lazy var leftBtn: UIBarButtonItem = {
let button = UIButton(type: .system)
button.setImage(UIImage(systemName: "arrow.turn.up.left"), for: .normal)
button.sizeToFit()
button.addTarget(self,
action: #selector(self.popToRoot(_:)),
for: .touchUpInside)
return UIBarButtonItem(customView: button)
}()
init(window: UIWindow, tabBarController: UITabBarController) {
self.tabBarController = tabBarController
childCoordinators = []
self.presenter = UINavigationController()
}
func start() {
performGetTabBar()
self.presenter.delegate = self
}
private func performGetTabBar() {
let coordinators: [Coordinator] = generateTabCoordinators()
coordinators.forEach({ coordinator in
coordinator.start()
addChildCoordinator(coordinator)
})
let presenters: [UIViewController] = coordinators.map({ coordinator -> UIViewController in
return coordinator.presenter
})
leftBtn.style = .plain
tabBarController?.navigationItem.leftBarButtonItem = leftBtn
tabBarController?.setViewControllers(presenters, animated: false)
selectTab(type: SurfTripCoordinator.self)
}
private func generateTabCoordinators() -> [Coordinator] {
let calculatorCoordinator: CalculatorCoordinator = CalculatorCoordinator(presenter: UINavigationController())
let tripCoordinator: SurfTripCoordinator = SurfTripCoordinator(presenter: UINavigationController())
let sellCoordinator: SavedTripsCoordinator = SavedTripsCoordinator(presenter: UINavigationController())
return [calculatorCoordinator, tripCoordinator, sellCoordinator]
}
*//this is not being called when coming from vertical flow*
@objc func popToRoot(_ sender: UIBarButtonItem) {
let storyboard: UIStoryboard = UIStoryboard(name: Constants.Storyboards.welcomeViewCoordinator, bundle: nil)
let controller: WelcomeViewController = WelcomeViewController.instantiate(from: storyboard)
tabBarController?.navigationController?.pushViewController(controller, animated: true)
}
}
extension TabBarCoordinator: UINavigationControllerDelegate {
func selectTab<T: Coordinator>(type _: T.Type) {
guard let index = childCoordinators.firstIndex(where: { coordinator in
coordinator is T
}) else {
return
}
tabBarController?.selectedIndex = index
}
}
and here is the current WelcomeCoordinator set up这是当前的 WelcomeCoordinator 设置
class WelcomeCoordinator: NSObject, Coordinator {
internal var presenter: UINavigationController
var childCoordinators: [Coordinator]
init(window: UIWindow, presenter: UINavigationController) {
self.presenter = presenter
childCoordinators = []
}
func start() {
let storyboard: UIStoryboard = UIStoryboard(name: Constants.Storyboards.welcomeViewCoordinator, bundle: nil)
let controller: WelcomeViewController = WelcomeViewController.instantiate(from: storyboard)
controller.delegate = self
presenter.pushViewController(controller, animated: true)
}
}
extension WelcomeCoordinator : WelcomeViewControllerDelegate {
func performAddLevel() {
let addLevelCoordinator: AddLevelViewCoordinator = AddLevelViewCoordinator(presenter: UINavigationController())
addLevelCoordinator.start()
addChildCoordinator(addLevelCoordinator)
addLevelCoordinator.presenter.modalPresentationStyle = .fullScreen
presenter.present(addLevelCoordinator.presenter, animated: true, completion: nil)
}
}
sorry for the long post I wish there was more reaktive native way to do this...对不起,我希望有更多的本地方式来做到这一点......
Ok so I found partlly a solution the back button solution for my case: not using pushViewController
or show
because it comes with back button.好的,所以我找到了部分解决方案,即我的案例的后退按钮解决方案:不使用pushViewController
或show
因为它带有后退按钮。 presenter.setViewControllers([tabCoordinator.tabBarController!], animated: true)
and there setting the navBar to hidden. presenter.setViewControllers([tabCoordinator.tabBarController!], animated: true)
然后将导航栏设置为隐藏。 I made my own navItem button to navigate to rootVC.我制作了自己的 navItem 按钮来导航到 rootVC。 Next step to allocate and remove all child tabBar coordinators on back tap recognized.下一步分配和删除所有子 tabBar 协调器识别后点击。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.