Swiftpack.co - idemche/HierarchyUI as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by idemche.
idemche/HierarchyUI 0.1.2
Implementation of declarative UIKit application navigation for SwiftUI
⭐️ 10
🕓 42 weeks ago
iOS
.package(url: "https://github.com/idemche/HierarchyUI.git", from: "0.1.2")

HierarchyUI

CI Status Version License Platform

SwiftUI is a declarative UI layouting framework. HierarchyUI is a declarative UI navigation construction framework.

As Apple states in its official documentation: SwiftUI uses a declarative syntax, so you can simply state what your user interface should do. For example, you can write that you want a list of items consisting of text fields, then describe alignment, font, and color for each field. Your code is simpler and easier to read than ever before, saving you time and maintenance.

SwiftUI's implementation implies that Navigation is embedded into UI layout, within NavigationLink. That creates some limitation in terms of different architectures which tend to separate UI from business and navigation logic.

HierarchyUI provides a way to create a readable and simple way to create a declarative Navigation structure separately, without mixing it with UI.

Your whole navigation structure can be in one file, the example of such navigation is:


import HierarchyUI

struct ExampleMainNavigationHierarchy: NavigationHierarchy {
    func structure() -> NavigationHierarchyRoute {
        View1().route(key: "1").pushes {
            View2().route(key: "2").pushes {
                View3().route(key: "3").pushes {
                    View4().route(key: "4").pushes {
                        [
                            View5().route(key: "5"),
                            View6().route(key: "6").pushes {
                                View8().route(key: "8").pushes {
                                    View9().route(key: "9").pushes {
                                        View10().route(key: "10").pushes {
                                            View11().route(key: "11").replaces {
                                                ExampleTabBarHierarchy().structure()
                                            }
                                        }
                                    }
                                }
                            },
                            View7().route(key: "7"),
                        ]
                    }
                }
            }.modals {
                View12().route(key: "12").pushes {
                    View13().route(key: "13").pushes {
                        View14().route(key: "14")
                    }
                }
            }
        }
    }
}

Create Navigation Structure

Let us consider you have several Views:

View1 View2 View3

And you need to organize them into simple push/pop navigation stack.

For that, you need to create a separate NavigationHierarchy:

Highlights:

Here's an example Here's the initial rendering result
Create a `NavigationHierarchy`
struct MainNavigationHierarchy: NavigationHierarchy {
    func structure() -> NavigationHierarchyRoute {
        View1().route(key: "1").pushes {
            View2().route(key: "2").pushes {
                View3().route(key: "3")
            }
        }
    }
}
and then render this hierarchy within AppDelegate
 @UIApplicationMain
 final class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let renderer = NavigationHierarchyRouteRenderer()
func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool {
self.window = UIWindow()
let hierarchy = MainNavigationHierarchy() window?.rootViewController = renderer .render(hierarchy: hierarchy)
window?.makeKeyAndVisible()
return true } }

where .route(key: AnyHashable) creates a route in NavigationHierarchy, and .pushes {} method of View/NavigationHierarchyRoute determines which View is going to be pushed next from destination View.

Control Navigation

To control Navigation, you need to declare Navigation EnvironmentObject inside your View.

Navigation Example How it looks
Create a `View` with EnvironmentObject
struct View1: View {
    @EnvironmentObject var navigation: HierarchyNavigator
var body: some View { Button( action: {}, label: { Text("1") .frame( width: 100, height: 100, alignment: .center ) .foregroundColor(.white) }) .background(Color.green) } }
And then invoke push method
 struct View1: View {
    @EnvironmentObject var navigation: HierarchyNavigator
var body: some View { Button(action: { navigation.push() }, label: { Text("1") .frame( width: 100, height: 100, alignment: .center ) .foregroundColor(.white) }) .background(Color.green) } }

App-wise example


/// Startup
struct AppStartupNavigationHierarchy: NavigationHierarchy {
    func structure() -> NavigationHierarchyRoute {
        SplashLoadingView().route(key: "Splash").pushes {
            [
                MainScreenNavigationHierarchy().structure()
                AuthorizationFlowNavigationHierarchy().structure(),
            ]
        }
    }
}

/// Authorization Flow
struct AuthorizationFlowNavigationHierarchy: NavigationHierarchy {
    func structure() -> NavigationHierarchyRoute {
        LandingView().route(key: "Landing").pushes {
            LoginView().route(key: "Login").pushes {
                PasswordView().route(key: "Password").replaces {
                    MainScreenNavigationHierarchy().structure()
                }
            }
        }
    }
}

/// Main Screen
struct MainScreenNavigationHierarchy: NavigationHierarchy {
     func structure() -> NavigationHierarchyRoute {
        TabBarHierarchy(key: "MainTabBar", initialTabIndex: 0)
            .tab(tabBarSystemItem: .bookmarks) {
                BookmarksView().route("Bookmarks").pushes {
                    BookmarksDetailsView().route("BookmarksDetails")
                }
                .modals {
                    BookmarksTutorialView().route("Bookmarks Tutorial View")
                }
            }
            .tab(tabBarSystemItem: .contacts) {
                 ContactsView().route("Contacts").pushes {
                    ContactsDetailsView().route("ContactsDetails")
                }
                .modals {
                    ContactsTutorialView().route("Contacts Tutorial View")
                }
            }
            .tab(tabBarSystemItem: .downloads) {
                 DownloadsView().route("Downloads").pushes {
                    DownloadsDetailsView().route("DownloadsDetails")
                }
                .modals {
                    DownloadsTutorialView().route("Downloads Tutorial View")
                }
            }
            .tab(tabBarSystemItem: .favorites) {
                FavoritesView().route("Favorites").pushes {
                    FavoritesDetailsView().route("FavoritesDetails")
                }
                .modals {
                    FavoritesTutorialView().route("Favorites Tutorial View")
                }
            }
            .build()
    }
}

Requirements

Swift 5.x iOS 13.0+

Installation

HierarchyUI is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'HierarchyUI'

Author

idemche, [email protected]

License

HierarchyUI is available under the MIT license. See the LICENSE file for more info.

GitHub

link
Stars: 10
Last commit: 2 weeks ago
jonrohan Something's broken? Yell at me @ptrpavlik. Praise and feedback (and money) is also welcome.

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics