RouteStack allows you to manage navigation and presentation states as a single stack in SwiftUI.
💁🏻♂️ It supports iOS 16 and later.
💁🏻♂️ Implemented purely using SwiftUI.
💁🏻♂️ Based on NavigationStack implementation.
💁🏻♂️ Supports various options for sheets (Presentation Detents, Presentation Drag Indicator).
✅ With RouteStack, you can easily apply the Coordinator pattern in SwiftUI.
✅ By using RouteStack and Deeplinks together, you can achieve a one-to-one relationship between scenes and deeplinks.
✅ RouteStack allows you to easily present views using different methods such as push, sheet, cover, etc.
You can achieve sophisticated routing with simple code.
For detailed usage, please refer to the example code.
enum Path: Hashable {
case first(String)
case second(String)
case third(String)
}
struct ContentView: View {
@State var routePaths: RoutePaths<Path> = .init()
@ViewBuilder
func root() -> some View {
// Define the root view here.
}
var body: some View {
RouteStack($routePaths, root: root) { id, path in
switch path {
// Define path views here. You can use a switch statement to define views based on the path.
}
}
}
}You can update routePaths using the Array-based functions API:
struct ContentView: View {
@State var routePaths: [RoutePath<Path>] = .init()
@ViewBuilder
func root() -> some View {
Button("push") {
routePaths.append(.init(data: Path.first("value"), style: .push))
}
Button("custom-sheet") {
routePaths.append(.init(data: Path.first("value"), style: .sheet([.medium, .large], .visible)))
}
Button("normal") {
routePaths.append(.init(data: Path.first("value"), style: .sheet()))
}
Button("cover") {
routePaths.append(.init(data: Path.first("value"), style: .push))
}
Button("cover -> push -> push") {
routePaths.append(contentsOf: [
.init(data: Path.first("value"), style: .cover),
.init(data: Path.first("value"), style: .push),
.init(data: Path.first("value"), style: .push),
])
}
Button("backToRoot") {
routePaths.removeAll()
}
Button("back") {
routePaths.removeLast()
}
}
var body: some View {
// Omitted
}
}You can use deeplinks to transition between views without directly accessing routePaths.
struct ContentView: View {
@State var routePaths: [RoutePath<Path>] = .init()
@ViewBuilder
func root() -> some View {
// Omitted
}
var body: some View {
RouteStack($routePaths, root: root) { id, path in
// Omitted
Button("work") {
UIApplication.shared.open(URL(string: "routeStackExample://backToRoot")!)
}
// Omitted
}
.onOpenURL { url in
// Update the routePaths value based on the information received from the deeplink URL.
}
}
}dependencies: [
.package(url: "https://github.com/Monsteel/RouteStack.git", .upToNextMajor(from: "0.0.1"))
]I'm open to contributions and improvements for anything that can be enhanced.
Feel free to contribute through Pull Requests. 🙏
RouteStack is available under the MIT license. See the LICENSE file for more info.
Tony | dev.e0eun@gmail.com