如何通过 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))")
}
我正在尝试通过 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))")
}