Swift 如何从协调器类更新EnvironmentObject变量?

Swift 如何从协调器类更新EnvironmentObject变量?,swift,firebase-authentication,swiftui,coordinator-pattern,Swift,Firebase Authentication,Swiftui,Coordinator Pattern,当用户通过FB登录按钮完成授权时,我使用Coordinator(符合LoginButtoneLegate)对象来接收用户数据(配置文件、名称)。 Coordinator().userId属性使用用户ID更新,但我需要将其传递到LoginView的1级,并更新名为thisSession的EnvironmentObject(以某种方式使thisSession.userId=Coordinator().userId) 有办法吗?我尝试使用ObserveObject/已发布属性,但无法从Coordina

当用户通过FB登录按钮完成授权时,我使用Coordinator(符合LoginButtoneLegate)对象来接收用户数据(配置文件、名称)。 Coordinator().userId属性使用用户ID更新,但我需要将其传递到LoginView的1级,并更新名为thisSession的EnvironmentObject(以某种方式使thisSession.userId=Coordinator().userId)

有办法吗?我尝试使用ObserveObject/已发布属性,但无法从Coordinator更新父对象的属性

另一个想法是订阅Auth.Auth()更改,但它似乎太复杂,有点“老派”的解决方案。我错过了一些简单的方法

有什么提示/想法吗

import SwiftUI
import FirebaseCore
import FirebaseAuth
import FBSDKLoginKit
import FBSDKCoreKit

struct LoginView: View {
    @EnvironmentObject var thisSession: CurrentSession
    @ObservedObject var mainData = MainViewModel()

    var facebookView = facebook()

    var body: some View {
        VStack {
            facebookView.frame(width: 240, height: 50)
            Text("\(self.thisSession.userId ?? "none")")
        }
    }
}

struct LoginView_Previews: PreviewProvider {
    static var previews: some View {
        LoginView().environmentObject(CurrentSession())
    }
}


struct facebook: UIViewRepresentable {
    @EnvironmentObject var thisSession: CurrentSession
    @ObservedObject var coordinator = Coordinator()

    func makeCoordinator() -> facebook.Coordinator {
        return self.coordinator
        //facebook.Coordinator()
    }

    func makeUIView(context: UIViewRepresentableContext<facebook>) -> FBLoginButton {

        let button = FBLoginButton()
        button.delegate = self.coordinator
        print("UPDATED")

        return button
    }

    func updateUIView(_ uiView: FBLoginButton, context: UIViewRepresentableContext<facebook>) {
    }

    class Coordinator: NSObject, LoginButtonDelegate, ObservableObject {
        @Published var userId: String?
        func loginButton(_ loginButton: FBLoginButton, didCompleteWith result: LoginManagerLoginResult?, error: Error?) {

            if error != nil{

                print((error?.localizedDescription)!)
                return
            }
            if AccessToken.current != nil{

                let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)

                Auth.auth().signIn(with: credential) { (res,er) in

                    if er != nil{
                        print((er?.localizedDescription)!)
                        return

                    }
                    print("email: \(String(describing: res?.user.email))")
                    print("name: \(String(describing: res?.user.displayName))")
                    self.userId = String(describing: res?.user.displayName)
                }
            }
        }

        func loginButtonDidLogOut(_ loginButton: FBLoginButton) {
            print("logged out")
            try! Auth.auth().signOut()

        }
    }

}
导入快捷界面
导入FirebaseCore
导入FirebaseAuth
导入FBSDKLoginKit
导入FBSDKCoreKit
结构逻辑视图:视图{
@环境对象变量thisSession:CurrentSession
@ObservedObject var mainData=MainViewModel()
var facebookView=facebook()
var body:一些观点{
VStack{
facebookView.框架(宽:240,高:50)
文本(\(self.thisSession.userId??“无”))
}
}
}
结构LoginView\u预览:PreviewProvider{
静态var预览:一些视图{
LoginView().environmentObject(CurrentSession())
}
}
结构facebook:UIViewRepresentable{
@环境对象变量thisSession:CurrentSession
@ObservedObject变量协调器=协调器()
func makeCoordinator()->facebook.Coordinator{
返回自我协调器
//facebook.Coordinator()
}
func makeUIView(上下文:UIViewRepresentableContext)->FBLoginButton{
let button=FBLoginButton()
button.delegate=self.coordinator
打印(“更新”)
返回按钮
}
func updateUIView(uiView:FBLoginButton,context:UIViewRepresentableContext){
}
类协调器:NSObject、loginbuttonelegate、observeObject{
@发布的var userId:String?
func loginButton(loginButton:FBLoginButton,didComplete结果:LoginManager LoginResult?,错误:error?){
如果错误!=nil{
打印((错误?.localizedDescription)!)
返回
}
如果AccessToken.current!=nil{
让credential=FacebookAuthProvider.credential(withAccessToken:AccessToken.current!.tokenString)
Auth.Auth().signIn(带:凭证){(res,er)in
如果er!=零{
打印((er?.localizedDescription)!)
返回
}
打印(“电子邮件:\(字符串(描述:res?.user.email)))
打印(“名称:\(字符串(描述:res?.user.displayName)))
self.userId=String(描述:res?.user.displayName)
}
}
}
func loginButtonDidLogOut(loginButton:FBLoginButton){
打印(“注销”)
试试!Auth.Auth().signOut()
}
}
}

尝试以下操作,因为协调器是在更新过程中创建的,环境对象应该已经被注入并存在,所以它应该可以工作

struct facebook: UIViewRepresentable {
    @EnvironmentObject var thisSession: CurrentSession

    func makeCoordinator() -> facebook.Coordinator {
        Coordinator(session: thisSession)              // << here !!
    }

    func makeUIView(context: UIViewRepresentableContext<facebook>) -> FBLoginButton {

        let button = FBLoginButton()
        button.delegate = self.coordinator
        print("UPDATED")

        return button
    }

    func updateUIView(_ uiView: FBLoginButton, context: UIViewRepresentableContext<facebook>) {
    }

    class Coordinator: NSObject, LoginButtonDelegate, ObservableObject {
        let session: CurrentSession
        init(session: CurrentSession) {
            self.session = session
        }

        func loginButton(_ loginButton: FBLoginButton, didCompleteWith result: LoginManagerLoginResult?, error: Error?) {

            if error != nil{

                print((error?.localizedDescription)!)
                return
            }
            if AccessToken.current != nil{

                let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)

                Auth.auth().signIn(with: credential) { (res,er) in

                    if er != nil{
                        print((er?.localizedDescription)!)
                        return

                    }
                    print("email: \(String(describing: res?.user.email))")
                    print("name: \(String(describing: res?.user.displayName))")

                    DispatchQueue.main.async {   // << here 
                        self.session.userId = String(describing: res?.user.displayName)
                    }
                }
            }
        }

        func loginButtonDidLogOut(_ loginButton: FBLoginButton) {
            print("logged out")
            try! Auth.auth().signOut()

        }
    }

}
struct-facebook:UIViewRepresentable{
@环境对象变量thisSession:CurrentSession
func makeCoordinator()->facebook.Coordinator{
协调员(会话:thisSession)//FBLoginButton{
let button=FBLoginButton()
button.delegate=self.coordinator
打印(“更新”)
返回按钮
}
func updateUIView(uiView:FBLoginButton,context:UIViewRepresentableContext){
}
类协调器:NSObject、loginbuttonelegate、observeObject{
让会话:CurrentSession
初始化(会话:当前会话){
self.session=会话
}
func loginButton(loginButton:FBLoginButton,didComplete结果:LoginManager LoginResult?,错误:error?){
如果错误!=nil{
打印((错误?.localizedDescription)!)
返回
}
如果AccessToken.current!=nil{
让credential=FacebookAuthProvider.credential(withAccessToken:AccessToken.current!.tokenString)
Auth.Auth().signIn(带:凭证){(res,er)in
如果er!=零{
打印((er?.localizedDescription)!)
返回
}
打印(“电子邮件:\(字符串(描述:res?.user.email)))
打印(“名称:\(字符串(描述:res?.user.displayName)))

DispatchQueue.main.async{//不确定你们是否理解正确。我想用协调器的数据更新环境对象。@eugene_prg,EnvironmentObject只是对ObserveObject引用的一个观察者包装,所以在建议的解决方案中,该引用被传递到协调器中,并按预期进行更改。协调器如何访问环境对象的引用?我们甚至在创建协调器时不传递引用,而是传递值。那么它如何更新它呢?