0

I am a newbie in swift development with iOS. Currently I have started a project in Swift with SwiftUI that has different hierarchies of views. There are different switches between the views. I have attached a picture (architectur). My current problem is that switching between the views does not work properly for the right area (if no credentials are available) (consequently, of course, not for the left area either).

Currently I use NavigationView because I want to support iOS 15. In the @main I have placed the NavigationView and in this is the StartView as parent root. I tried to switch from the child views with the navigation link, using tag and selection via a button as the example for iOS 15 in this tutorial. Another attempt was the following code, in which currently only the right area and the mainview are implemented:

final class NavigationManager: ObservableObject {
    
    @Published var view: Views? {
        didSet {
            print("View \(view)")
        }
    }
    
    func push(to view: Views) {
        self.view = view
    }
    
    func popToRoot() {
        view = nil
    }
}

enum Views {
    case startView
    case loginView
    case mainView
    case aboutView
    case cred1View
    case cred2View
}

Unfortunately the navigation does not work as desired. Does anyone have any tips on navigation for the architecture I mentioned?

2
  • 5
    Strong suggestion, if you are new to this, just support the latest version of iOS. SwiftUI is advancing by huge leaps with each release and by forcing yourself to support older versions you're learning outdated stuff and building in tech debt from the start. Commented Mar 13, 2024 at 15:21
  • Please provide enough code so others can better understand or reproduce the problem. Commented Mar 14, 2024 at 18:55

1 Answer 1

0

You can create Router like this with NavigationPath() publisher.

final class NavigationManager: ObservableObject {
    
    public enum Destination: Codable, Hashable {
        case loginView
        case mainView
    }
    
    @Published var navPath = NavigationPath()
    
    func navigate(to destination: Destination) {
        navPath.append(destination)
    }
    
    func navigateBack() {
        navPath.removeLast()
    }
    
    func navigateToRoot() {
        navPath.removeLast(navPath.count)
    }
}

For the Entry point you can init NavigationStack and bind router's path to it. and also pass router to its child views as enviroment object

@main
struct TestApp: App {
    @StateObject var router = NavigationManager()
    var body: some Scene {
        WindowGroup {
            NavigationStack(path: $router.navPath) {
                StartView()
                    .navigationDestination(for: NavigationManager.Destination.self) { destination in
                        switch destination {
                        case .loginView:
                                LoginView()
                        case .mainView:
                            MainView()
                        }
                    }
            }
            .environmentObject(router)
        }
    }
}

And finally trigger the view with isLoggedin logic like this. I'm sure you will have this logic in viewModel.

struct StartView: View {
    @EnvironmentObject var router: NavigationManager
    @State var isLoggedIn = false
    var body: some View {
        VStack {
            Image(systemName: "globe")
        }
        .padding()
        .onAppear {
            router.navigate(to: isLoggedIn ? .mainView : .loginView)
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

ObservedObject Is being misused
Changed to @StateObject, I hope thats what you meant. Thanks mate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.