Skip to content

Commit

Permalink
feature(tab bar coordinator): add support for transition action when …
Browse files Browse the repository at this point in the history
…starting the flow
  • Loading branch information
erikdrobne committed Jun 19, 2024
1 parent a7374f5 commit 2a87d7c
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,23 @@ extension TabsCoordinator: RouterViewFactory {
public func view(for route: TabsCoordinatorRoute) -> some View {
switch route {
case .red:
Text("Red")
VStack {
Circle()
.foregroundStyle(.red)
}
.padding(16)
case .green:
Text("Green")
VStack {
Circle()
.foregroundStyle(.green)
}
.padding(16)
case .blue:
Text("Blue")
VStack {
Circle()
.foregroundStyle(.blue)
}
.padding(16)
}
}
}
59 changes: 1 addition & 58 deletions Sources/SwiftUICoordinator/Navigator/Navigator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public protocol Navigator: ObservableObject {
/// The starting route of the navigator.
var startRoute: Route { get }

/// This method should be called to start the flow and to show the view for the `startRoute`.
/// This method should be called to start the flow and to show the view for the `startRoute`.
func start() throws
/// It creates a view for the route and adds it to the navigation stack.
func show(route: Route) throws
Expand Down Expand Up @@ -106,25 +106,6 @@ public extension Navigator where Self: RouterViewFactory {
}

// MARK: - Private methods

private func hostingController(for route: Route) -> UIHostingController<some View> {
let view: some View = self.view(for: route)
.ifLet(route.title) { view, value in
view.navigationTitle(value)
}
.if(route.attachCoordinator) { view in
view.environmentObject(self)
}

return RouteHostingController(
rootView: view,
route: route
)
}

private func views(for routes: [Route]) -> [UIHostingController<some View>] {
return routes.map { self.hostingController(for: $0) }
}

private func present(
viewController: UIViewController,
Expand All @@ -143,41 +124,3 @@ public extension Navigator where Self: RouterViewFactory {
navigationController.present(viewController, animated: animated, completion: completion)
}
}

public typealias TabBarRouting = Coordinator & TabBarCoordinatable

@MainActor
public protocol TabBarCoordinatable: ObservableObject {
associatedtype Route: TabBarNavigationRoute

var navigationController: NavigationController { get }
var tabBarController: UITabBarController { get }
var tabs: [Route] { get }
func start()
}

public extension TabBarCoordinatable where Self: RouterViewFactory {
func start() {
tabBarController.viewControllers = views(for: tabs)
navigationController.pushViewController(tabBarController, animated: true)
}

private func views(for routes: [Route]) -> [UIHostingController<some View>] {
return routes.map { self.hostingController(for: $0) }
}

private func hostingController(for route: Route) -> UIHostingController<some View> {
let view: some View = self.view(for: route)
.ifLet(route.title) { view, value in
view.navigationTitle(value)
}
.if(route.attachCoordinator) { view in
view.environmentObject(self)
}

return RouteHostingController(
rootView: view,
route: route
)
}
}
21 changes: 21 additions & 0 deletions Sources/SwiftUICoordinator/Routing/RouterViewFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,24 @@ public protocol RouterViewFactory {
@ViewBuilder
func view(for route: Route) -> V
}

extension RouterViewFactory where Self: ObservableObject {
func hostingController(for route: Route) -> UIHostingController<some View> {
let view: some View = self.view(for: route)
.ifLet(route.title) { view, value in
view.navigationTitle(value)
}
.if(route.attachCoordinator) { view in
view.environmentObject(self)
}

return RouteHostingController(
rootView: view,
route: route
)
}

func views(for routes: [Route]) -> [UIHostingController<some View>] {
return routes.map { self.hostingController(for: $0) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import SwiftUI

public typealias TabBarRouting = Coordinator & TabBarCoordinator

/// A protocol for managing a tab bar interface in an application.
@MainActor
public protocol TabBarCoordinator: ObservableObject {
associatedtype Route: TabBarNavigationRoute

var navigationController: NavigationController { get }
var tabBarController: UITabBarController { get }
var tabs: [Route] { get }
/// This method should be called to show the `tabBarController`
func start(with action: TransitionAction)
}

public extension TabBarCoordinator where Self: RouterViewFactory {
func start(with action: TransitionAction = .push(animated: true)) {
tabBarController.viewControllers = views(for: tabs)

switch action {
case .push(let animated):
navigationController.pushViewController(tabBarController, animated: animated)
case .present(let animated, let modalPresentationStyle, let delegate, let completion):
present(
viewController: tabBarController,
animated: animated,
modalPresentationStyle: modalPresentationStyle,
delegate: delegate,
completion: completion
)
}
}

// MARK: - Private methods

private func present(
viewController: UITabBarController,
animated: Bool,
modalPresentationStyle: UIModalPresentationStyle,
delegate: UIViewControllerTransitioningDelegate?,
completion: (() -> Void)?
) {
if let delegate {
viewController.modalPresentationStyle = .custom
viewController.transitioningDelegate = delegate
} else {
viewController.modalPresentationStyle = modalPresentationStyle
}

navigationController.present(viewController, animated: animated, completion: completion)
}
}

0 comments on commit 2a87d7c

Please sign in to comment.