如何通过 Google 登录来使用 ObservedObject

How to use ObservedObject with Google Sign In

我正在尝试通过 Google 使用 SwiftUI 登录 SDK 来观察用户是否登录。登录工作正常,打印输出显示用户已成功登录,但 UI 没有改变,就像观察不工作一样,或者我确定我错过了一些东西。

应用程序:

@main
struct test_app: App {
    
    @AppStorage("settings") private var settings: Data = Data()
    @Environment(\.scenePhase) var scenePhase
    @UIApplicationDelegateAdaptor(test_delegate.self) private var appDelegate
    
    var userInfo:Bool = false
    @ObservedObject static var gd = GoogleDelegate()
    
    init(){
        //Google sign in
        GIDSignIn.sharedInstance().delegate = test_app.gd
        //Firebase
        FirebaseApp.configure()
        print("[APP] Init complete.")
    }
    
    var body: some Scene {
        WindowGroup {
            
            if userInfo  {
                w_home().onOpenURL(perform: { url in
                                   print("[DEEP LINK] Incoming url: \(url)")
                                    })
            }else{
                w_splash()
            }
            
        }.onChange(of: scenePhase) { (newScenePhase) in
            switch newScenePhase {
            case .background:
                print("[APP] State : Background")
            case .inactive:
                print("[APP] State : Inactive")
            case .active:
                
                print("[APP] State : Active")
            @unknown default:
                print("[APP] State : Unknown")
            }
        }
    }
}

Google委托 class :

class GoogleDelegate: NSObject, GIDSignInDelegate, ObservableObject {
    
    @Published var signedIn: Bool = false
    
    public func signIn(){
        
        // Maksure that there must be a presenting controller as a container
        GIDSignIn.sharedInstance()?.presentingViewController = UIApplication.shared.windows.first?.rootViewController
        
        //Google sign in
        GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
        GIDSignIn.sharedInstance().signIn()
        
        signedIn = false
        
    }
    
    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
        if let error = error {
            if (error as NSError).code == GIDSignInErrorCode.hasNoAuthInKeychain.rawValue {
                print("[GSIN] The user has not signed in before or they have since signed out.")
            } else {
                print("[GSIN] \(error.localizedDescription)")
            }
            return
        }
        
        // If the previous `error` is null, then the sign-in was succesful
        if GIDSignIn.sharedInstance().currentUser != nil {
            print("[GSIN] Successful sign-in! \( String(describing: GIDSignIn.sharedInstance().currentUser!.profile.email) )")
        }else{
            print("[GSIN] Successful sign-in!")
        }
        
       self.signedIn = true

    }
    
}

最后登录:

struct w_splash: View {
    
    let screenBounds:CGRect = UIScreen.main.bounds
    
    var body: some View {
        ZStack {
                Image("logo").resizable()
                             .aspectRatio(contentMode: .fit)
                             .frame(width: screenBounds.width * 0.5, height: screenBounds.height * 0.2)
                VStack {
                    
                        Spacer()
               
                        HStack {
                            
                        
                            Button(action: {
                            
                                test_app.gd.signIn()
                                
                            }, label: {
                                
                                HStack{
                                    Image("btn_google_dark_normal_ios").resizable().frame(width: 50, height: 50, alignment: .center)
                                    
                                    Text("Sign in with Google")
                                        .font( Font.custom("Roboto-Medium", size: 14) )
                                        .frame(width: .none,
                                               height: 50,
                                               alignment: .center)
                                    .foregroundColor(Color.white)
                                        .padding(.trailing, 30)
                                        .padding(.leading, 10)
                                }
                            })
                            .isHidden(test_app.gd.signedIn)
                            .background(Color(hex: "#4285F4"))
                            .cornerRadius(5.5)
                            .padding(.bottom , screenBounds.height * 0.1)
                            .frame(width: screenBounds.width * 0.9,
                                   height: 50,
                                   alignment: .center)
                            .shadow(color: Color.black.opacity(0.2),
                                    radius: 3,
                                    x: 3,
                                    y: 3)
                        }
                    }
        }.onAppear{
            
            if (test_app.gd.signedIn ){
                
             print("user logged in test print out")
           
            }
            
        }
    }
}

struct w_splash_Previews: PreviewProvider {
    static var previews: some View {
        w_splash()
    }
}

我对 swift 还是个新手UI,为什么我不能观察变量有什么想法吗?

您似乎想将 GoogleDelegate 设为单例。

我建议你创建一个 GoogleDelegate:

的静态实例
class GoogleDelegate: NSObject, GIDSignInDelegate, ObservableObject {
    static let shared = GoogleDelegate()
    
    @Published var signedIn: Bool = false
    ...
}

然后,在您的视图中替换:

@ObservedObject static var gd = GoogleDelegate()

与:

@ObservedObject var gd = GoogleDelegate.shared

此外,请注意您在 w_splash 视图中没有观察到 GoogleDelegate,因此您也需要将其添加到那里:

struct w_splash: View {
    @ObservedObject var gd = GoogleDelegate.shared

并使用 gd.signedIn(而不是 test_app.gd.signedIn)直接引用它。

如果你想在 gd.signedIn 改变时 print 一些东西,你可以使用 onChange:

.onChange(of: gd.signedIn) { signedIn in
    print("signedIn: \(String(signedIn))")
}