This is a simple package to help perform programatic navigation in your app.
Defining your routes with destination
Wrap your destination function with @ViewBuilder
to be able to return any view.
// Your app routes
enum TestNavigationRoute: NavigationRoute {
case settings
case profile
case detailProfile(
var id: String {
switch self {
case .settings: return "test.settings"
case .profile: return "test.profile"
case .detail
}
}
@ViewBuilder func destination(from:Namespace.ID) -> some View {
switch self {
case .settings: return Text("Settings destination")
case .profile: return Text("Profile destination")
}
}
}
For routes with data you can use any data of choice. But if you are like me who sometimes need to pass binding to some state properties from the calling site and also perform some matchedGeometry animations, there's a helper struct to help bundle all together.
// Define struct to be used inside your view
struct EditProfileConfig:ViewConfig {
var isEditing:Bool = false
var isScrolling: Bool = false
}
// Instantiate config in your view
@State var config:EditProfileConfig = .init()
// Define your route with data.
enum TestNavigationRoute: NavigationRoute {
typealias ProfileEditData = NavigationData<Profile, EditProfileConfig>
...
case detailProfile(Profile) // route with regular data
case editProfile(ProfileEditData) // route with complex data
var id: String {
switch self {
...
case .detailProfile: return "test.profile.detail"
case .editProfile: return "test.profile.edit"
}
}
@ViewBuilder func destination(from:Namespace.ID) -> some View {
switch self {
...
case .detailProfile(let profile): return ProfileDetailView(profile:profile)
case .editProfile(let data): return EditProfileView(profile:data.value, config:data.config, namespace:data.namespace)
}
}
}
If you don't want to associate value, config and namespace with your routes, You can use other convenience methods to associate variations.
NavigationDataValue
will give you only dataNavigationDataWithConfig
gives you data with a configNavigationDataWithNamespace
gives you data with namespace.
To perform navigation from your views, we have to options
navigateTo
environment variable You can access this from the environment and pass to it an instance ofAnyNavigationRoute
.
// Get environment variable
@Environment(\.navigateTo) var navigateTo
// use the environment variable with an instance of AnyNavigationRoute
// AR is a typealias to AnyNavigationRoute
navigateTo(AR(TestNavigationRoute.settings))
- Use
NavigationLink(value:label)
to push view
NavigationLink(
value: AR(TestRoutes.profile)
) {
ProfileListItemView()
}
- Finally, use
AppNavigationView(content:)
to host your views and perform navigation.
AppNavigationView {
ContentView()
}
AppNavigationView
injects the navigateTo(_)
into the environment of the ContentView to be accessible in child views.
If you want to add navigation title to your view, the modifier should either be applied to the ContentView
or a sub view in ContentView
.
You can also use the goBack
environment variable to pop a view off the navigation stack.