skip to Main Content

In my application I start with a LoginView which makes an API call to the backend for authentication. In case this is successfull (in a completion handler, i want to show the FeedView().
With UIKit this is all pretty simple trying to figure out how to do this with SwiftUI.
So How can I show a new View programmatically (I don’t have a NavigationView)?

3

Answers


  1. You can have a conditional view like so:

    struct MakeSureUserIsLoggedInView: View {
      @State private var loggedIn = false
      var body: some View {
        if loggedIn {
          FeedView()
        } else {
          LoginView { // your login view with completion handler
            loggedIn = true
          }
        }
      }
    }
    

    Notice how we use @State to switch between what view is shown.

    Login or Signup to reply.
  2. If you don’t want to use a NavigationView, you have several options:

    1. A SwiftUI-native style would be simply to have a parent view which
      holds your view, and other views. You can have a property on a
      shared ViewModel and the parent view can return a different child
      view depending on the value of the view model

    2. Displaying a new view modally (this is easiest)

    3. Using UIKit navigation – this is my preferred method in complex apps where you can simply navigate around the app using UIViewControllers, with a SwiftUI view pinned to the edges

    I can go into more detail on any of these, with some sample code from my own projects, if you would like. Option 1 is probably the most natural for SwiftUI and you can even animate the transitions pretty nicely with things like matchedGeometryView if you use this option.

    Login or Signup to reply.
  3. You could use EnvironmentObject to control your user Session, the example below is with Firebase Authentication. Take care you need to add an environmentObject in your parent view.

    Main:

    import SwiftUI
    import Firebase
    
    @main
    struct YourApp: App {
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(SessionManager.shared)
        }
    }
    
    //Firebase init
    class AppDelegate: NSObject, UIApplicationDelegate {
        func application(_ application: UIApplication,   didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            FirebaseApp.configure()
            return true
          }
    }
    }
    

    ContentView: access your environment var

    struct ContentView: View {
    
    @EnvironmentObject var session: SessionManager
    
    var body: some View {
        
        Group {
            if session.loggedUser != nil {
                FeedView()
            }
            else {
                LoginView()
            }
    }
    }
    

    Sample Session Manager (Firebase sample, if you have another backend you need to add your logic). Then is possible to call logout wherever you want in your app, this action change ContentView State and display LoginView:

    import Foundation
    import SwiftUI
    import Firebase
    
    class SessionManager: NSObject, ObservableObject {
        
        @Published var loggedUser: User?
        static let shared = SessionManager()
        private let auth = Auth.auth()
        
        var handle : AuthStateDidChangeListenerHandle?
        
        override private init() {
            loggedUser = auth.currentUser
            super.init()
            handle = auth.addStateDidChangeListener(authStateChanged)
        }
        
        private func authStateChanged(with auth: Auth, user: User?) {
            guard user != self.loggedUser else { return }
            self.loggedUser = user
        }
            
        func logout() {
            do {
                try Auth.auth().signOut()
            } catch(let error) {
                debugPrint(error.localizedDescription)
            }
        }
        
        func unbind() {
            if let handle = handle {
                Auth.auth().removeStateDidChangeListener(handle)
            }
        }
        
        deinit {
            unbind()
        }
        
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search