swift - 如何通过 Google 登录使用 ObservedObject
问题描述
我正在尝试观察用户是否通过 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")
}
}
}
}
GoogleDelegate 类:
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()
}
}
我还是 swiftUI 的新手,有什么想法为什么我不能观察到变量?
解决方案
看起来你想做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
另外,请注意您没有GoogleDelegate
在w_splash
视图中观察,因此您还需要在此处添加它:
struct w_splash: View {
@ObservedObject var gd = GoogleDelegate.shared
gd.signedIn
并使用(not )直接引用它test_app.gd.signedIn
。
如果您想在更改print
时进行某些gd.signedIn
操作,可以使用onChange
:
.onChange(of: gd.signedIn) { signedIn in
print("signedIn: \(String(signedIn))")
}
推荐阅读
- javascript - 正则表达式不会在新行上回溯
- c# - c# 错误:“未处理 OleDB 异常。创建文件失败。”
- android - 由于 sqliteexception,调试构建变体无法启动
- php - 如何在nodejs中实现“gzencode”(PHP函数)
- nativescript - javax.net.ssl.sslexception 连接被对等方关闭
- google-apps-script - 我需要一个函数来比较两个日期以及如何将脚本更改为仅使用工作日
- ssh - 如何通过 pssh/fabric 库使用 lsof 命令?Bash:找不到 lsof 命令
- javascript - React:生成和保存 PDF onClick() 问题 - Kendo
- java - 如何将字符串的嵌套 PlaceHolders 映射到 Java 中的 Pojo 类
- json - 如何在 Flutter 中解析长度为 1 的 JSON 数组?