obvios / Routing

Routing library for abstracting navigation logic from SwiftUI views.
MIT License
67 stars 6 forks source link

Description

Routing is a library for separating navigation logic from SwiftUI views.

Requirements

Installation

You can install Routing using the Swift Package Manager.

  1. In Xcode, select "File" > "Add Packages...".
  2. Copy & paste the following into the "Search or Enter Package URL" search bar.
    https://github.com/obvios/Routing.git
  3. Xcode will fetch the repository & the "Routing" library will be added to your project.

Getting Started

  1. Create a Routable conforming Enum to represent the different views you wish to route to.
    
    import SwiftUI
    import Routing

enum ExampleRoute: Routable { case viewA case viewB(String) case viewC

@ViewBuilder
func viewToDisplay(router: Router<ExampleRoute>) -> some View {
    switch self {
    case .viewA:
        ViewA(router: router)
    case .viewB(let description):
        ViewB(router: router, description: description)
    case .viewC:
        ViewC(router: router)
    }
}

var navigationType: NavigationType {
    switch self {
    case .viewA:
        return .push
    case .viewB(_):
        return .sheet
    case .viewC:
        return .fullScreenCover
    }
}

}


2. Wrap your view hierarchy in a `RoutingView` that is initialized with your `Routable` enum. It will inject a `Router` instance into your root view.
```swift
import SwiftUI
import Routing

struct ContentView: View {
    var body: some View {
        RoutingView(ExampleRoute.self) { router in
            RootView(router: router)
        }
    }
}

struct RootView: View {
    @StateObject var router: Router<ExampleRoute>

    init(router: Router<ExampleRoute>) {
        _router = StateObject(wrappedValue: router)
    }

    var body: some View {
        VStack() {
            Button("View A") {
                router.routeTo(.viewA)
            }
            Button("View B") {
                router.routeTo(.viewB("Got here from RootView"))
            }
            Button("View C") {
                router.routeTo(.viewC)
            }
        }
    }
}
  1. Use the Router functions from any of your views. Here is ViewA which is pushed onto the navigation stack by RootView.

    struct ViewA: View {
    @StateObject var router: Router<ExampleRoute>
    
    init(router: Router<ExampleRoute>) {
        _router = StateObject(wrappedValue: router)
    }
    
    var body: some View {
        Text("View A")
        Button("ViewC") {
            router.routeTo(.viewC)
        }
        Button("Dismiss") {
            router.dismiss()
        }
    }
    }

Additional Resources

The below articles are from my blog series explaining the Router pattern and documents the progress of this library.