提问人:eugene_prg 提问时间:6/18/2020 更新时间:6/18/2020 访问量:1034
如何从协调器类更新EnvironmentObject变量?
How to update EnvironmentObject variable from Coordinator class?
问:
当用户通过FB登录按钮完成授权时,我正在使用Coordinator(符合LoginButtonDelegate)对象来接收用户数据(配置文件,名称)。 Coordinator().userId 属性更新为用户 ID,但我需要将其传递给 LoginView 1 级并更新名为 thisSession 的 EnvironmentObject(以某种方式使 thisSession.userId = Coordinator().userId)。
有什么办法可以做到吗?我尝试使用ObservableObject/Published属性,但无法从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()
}
}
}
答:
4赞
Asperi
6/18/2020
#1
尝试以下操作,因为协调器是在更新期间创建的,因此环境对象应该已经注入并存在,因此它应该可以工作
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()
}
}
}
评论
0赞
eugene_prg
6/18/2020
不知道你是否听对了。我想使用数据 FROM 协调器更新环境对象。
0赞
Asperi
6/18/2020
@eugene_prg,EnvironmentObject 只是对 ObservableObject 的引用的观察者包装器,因此在建议的解决方案中,此引用被传递到协调器中,并按预期更改它。
0赞
eugene_prg
6/18/2020
协调器如何访问 EnvironmentObject 的引用?我们甚至在创建协调器时不传递引用,而是传递 VALUE。那么它是如何更新的呢?
评论