简体   繁体   中英

How to show view after login view in swiftUI

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)?

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.

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.

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()
    }
    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM