0

In my app I have the user login with their google account to have the rest of the app personalized to their account, however after they login I want to have it automatically change views and go to the home screen, but I have not found a way to make it work without have a separate button that needs to be tapped after login to change the view.

Here is the code for the login page. I'm currently changing the view with a NavigationLink, but I would like to know a way to do it automatically after a user is signed in.

struct LoginPage: View {

    var body: some View {

        //Login Page
        NavigationView{
            ScrollView {
            VStack {
            VLargeCardView(image: "pad22finalsf", category: "Login", heading: "Welcome to PV Pocket!", author: "PAD22")
            //Google Sign In Button
            google()
                .frame(width: 200, height: 50)
            //Switch to main view after login
            NavigationLink(destination: MainView()) {
               ZStack {
                Rectangle()
                      .frame(width: 300, height: 50)
                      .cornerRadius(20)
                    .foregroundColor(.orange)
                  Text("Click here after sign in!")
                     .foregroundColor(.primary)
                     .font(Font.system(size: 25))
                  }
                }
                .navigationBarHidden(true) .navigationBarTitle("")
                }
            }
        }
    }
}

If it helps here is the code for the Google sign in button as well.

//Creates Google Sign In instance
struct google : UIViewRepresentable {

    @EnvironmentObject var settings: UserSettings

    func makeUIView(context: UIViewRepresentableContext<google>) -> GIDSignInButton {

        //Create Google Sign In Button
        let button = GIDSignInButton()
        button.colorScheme = .dark
        button.style = .wide

        //Add Scopes to Login
        GIDSignIn.sharedInstance().scopes.append("https://www.googleapis.com/auth/drive")
        GIDSignIn.sharedInstance().scopes.append("https://www.googleapis.com/auth/classroom.courses")
        GIDSignIn.sharedInstance().scopes.append("https://www.googleapis.com/auth/classroom.coursework.me")
        GIDSignIn.sharedInstance().scopes.append("https://www.googleapis.com/auth/calendar")

        //Restore Previous Login if it exists
        GIDSignIn.sharedInstance()?.restorePreviousSignIn()

        GIDSignIn.sharedInstance()?.presentingViewController = UIApplication.shared.windows.last?.rootViewController

        return button

    }
    func updateUIView(_ uiView: GIDSignInButton, context: UIViewRepresentableContext<google>) {

    }

}

Any help or info would be greatly appreciated!

Sean Oplinger
  • 39
  • 1
  • 6
  • `NavigationLink` can be activated programmatically, look for constructor with `isActive`, and be hidden - use `EmptyView()` as label. – Asperi Dec 11 '19 at 16:13
  • @Asperi, your advice looks good. Do I understand correctly: if I will have ```@State var isActive``` and use it like you wrote, I'll go to destination automatically, while opening this view again (if var will be ```true``` of course)? – Hrabovskyi Oleksandr Dec 11 '19 at 16:45
  • @Александр-Грабовский, you can see in [this my answer](https://stackoverflow.com/questions/59089400/swiftui-list-with-navigationlink-how-to-make-custom-highlight-on-tap/59093878?r=SearchResults&s=1|28.3718#59093878) the usage of NavigationLink in this way. – Asperi Dec 11 '19 at 17:01

1 Answers1

0

My solution for authentication/registration consists of several parts:

  1. There is observable final static class with some data, which I can take from UserDefaults. I think you want to persist some data and change it too:
import SwiftUI

final class UserData: ObservableObject {

    @Published var userName: String? {
        didSet {
            UserDefaults.standard.set(userName, forKey: "userName")
        }
    }

    init() {
        self.userName = UserDefaults.standard.string(forKey: "userName")
    }

}
  1. My first Home view have this EnvironmentObject of UserData and set it in SceneDelegate class:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
   // other staff

   func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 
        let homeView = Home()
            .environmentObject(UserData())
        // ...
        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(rootView: homeView)
            self.window = window
            window.makeKeyAndVisible()
        }
    }
    // ...
}
  1. Home view shows LoginPage or MainView depending on UserData:
struct Home: View {

    @EnvironmentObject var userData: UserData

    var body: some View {

        if self.userData.userName == nil {
            return AnyView(LoginPage())
        else {
            return AnyView(MainView())
        }

    }

}
  1. So in this solution you just need to set userName in LoginPage:
struct LoginPage: View {
    // your login view has the same user data, so user name changes for Home view too
    @EnvironmentObject var userData: UserData
    var body: some View {

        VStack {
            VLargeCardView(image: "pad22finalsf", category: "Login", heading: "Welcome to PV Pocket!", author: "PAD22")
            //Google Sign In Button
            google()
                .frame(width: 200, height: 50)
            // I don't know, how you get data, I didn't work with google. so quick code is:
                .onTapGesture {
                    // when you set userName, in Home view will show MainView at this moment
                    self.userData.userName = "Steve Jobs"
                }
        }       
    }
}
Hrabovskyi Oleksandr
  • 3,070
  • 2
  • 17
  • 36