在水平流iOS 12中的TabbarCoordinator中未调用后退按钮 [英] Back button not being called in TabbarCoordinator in horizontal flow iOS 12
问题描述
协调器模式是一个古老的话题,许多图书馆都试图解决它,我正在简单的示例应用程序中学习它.
我当前的设置是3个rootViewControlers:LoadingStateCoordinator
,WelcomeCoordinator
,TabBarCoordinator
,但是UIKit和协调器之间缺少连接.我正在尝试使用UINavigationController来实现它,但是没有调用该按钮.我需要一种方法来连接到后退按钮和一个可重用的协调器,可以将其按入并进行相应的分配(即没有RxSwift).*将欢迎"屏幕设置为父/主导航,并始终能够返回到它. *
因此,在用户从显示的模态视图(垂直流)中选择一种形式后,我会一按即显示TabBarCoordinator(水平).所有的viewControllers都为空.storyboard
,UIViewController和Coordinator都在TabBar之外.在这里,由于子选项卡协调器的设置,我只有一个协调器,并且需要在后退按钮点击时进行魔术操作.目前,仅当用户来自LoadingStateCoordinator时才调用此方法.我需要在那里将用户送回到欢迎"屏幕,以便他们可以更改入职设置.这是LoadingStateCoordinator的第一个代码:
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. I am trying to implement it with a UINavigationController but the button is not being called. 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). 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. Currenly this only being called when user comes from 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:
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()
}
}
}
这是TabBarCoordinator,需要执行回到欢迎"屏幕操作.当我显示popToRoot
功能时,它会按欢迎"屏幕,但是所有按钮都没有显示.我想这是保留周期的问题.我是否需要funadametally另一个设置?在此设置中是否有方法可以弹出popToRoot(vc)?我尝试过的结果以运行时错误弹出到不存在的控制器"结束.
需要执行此操作的TabBarCoordinator代码:
And here is the TabBarCoordinator that need to perform back to Welcome screen action. When I present popToRoot
function it pushes the Welcome screen but all the button there are disbled. 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? What I tryed ended with runtime error "poping to non existing controller".
TabBarCoordinator code that need to perform this:
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
}
}
这是当前的WelcomeCoordinator设置
and here is the current WelcomeCoordinator set up
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...
推荐答案
好,所以我部分找到了针对我的情况的后退按钮解决方案:不使用pushViewController
或show
,因为它带有后退按钮. presenter.setViewControllers([tabCoordinator.tabBarController!], animated: true)
,然后将navBar设置为隐藏.我制作了自己的navItem按钮以导航到rootVC.下一步,分配并删除已识别出的自来水上的所有子tabBar协调器.
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. presenter.setViewControllers([tabCoordinator.tabBarController!], animated: true)
and there setting the navBar to hidden. I made my own navItem button to navigate to rootVC. Next step to allocate and remove all child tabBar coordinators on back tap recognized.
这篇关于在水平流iOS 12中的TabbarCoordinator中未调用后退按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!