Open onmyway133 opened 3 years ago
Use a custom NavigationLink with EmptyView as the background, this failable initializer accepts Binding of optional value. This works well as the destination are made lazily.
NavigationLink
EmptyView
extension NavigationLink where Label == EmptyView { init?<Value>( _ binding: Binding<Value?>, @ViewBuilder destination: (Value) -> Destination ) { guard let value = binding.wrappedValue else { return nil } let isActive = Binding( get: { true }, set: { newValue in if !newValue { binding.wrappedValue = nil } } ) self.init(destination: destination(value), isActive: isActive, label: EmptyView.init) } } extension View { @ViewBuilder func navigate<Value, Destination: View>( using binding: Binding<Value?>, @ViewBuilder destination: (Value) -> Destination ) -> some View { background(NavigationLink(binding, destination: destination)) } }
Then in our OnboardView, we can check the destination and make according View
final class OnboardViewModel: ObservableObject { enum Destination { case email case confirm case avatar } @Published var destination: Destination? = .email func goTo(destination: Destination) { self.destination = destination } } struct OnboardView: View { @StateObject private var viewModel = OnboardViewModel() var body: some View { NavigationView { OnboardEmailView(viewModel: viewModel) .navigate(using: $viewModel.destination, destination: makeView) } } @ViewBuilder private func makeView(destination: OnboardViewModel.Destination) -> some View { switch destination { case .email: OnboardEmailView(viewModel: viewModel) case .confirm: OnboardConfirmView(viewModel: viewModel) case .avatar: OnboardAvatarView(viewModel: viewModel) } } }
Use a custom
NavigationLink
withEmptyView
as the background, this failable initializer accepts Binding of optional value. This works well as the destination are made lazily.Then in our OnboardView, we can check the destination and make according View
Reference