#google-cloud-firestore #swiftui #grand-central-dispatch #swift5
#google-cloud-firestore #swiftui #grand-central-dispatch #swift5
Вопрос:
Я пытаюсь использовать a DispatchQueue
для обновления своего пользовательского интерфейса, поэтому, когда Firebase аутентифицирует пользователя, я могу передать вновь созданные данные на следующий экран.
У меня есть a SignUpView
, который регистрирует пользователя, а затем переходит к a ProfileView
в случае успеха. Это ProfileView
позволяет пользователю добавлять более конкретные детали для приложения.
У меня есть userSession
объект, который успешно регистрирует пользователя, но не сразу обновляет пользовательский интерфейс на следующем экране. Вероятно, это связано с тем, что я неправильно использую DispatchQueue.main.async
, что я не могу использовать в теле View
конструктора в SwiftUI.
Вот View
я использую для заполнения имени пользователя в ProfileView
том, что я получаю от SignUpView
.
Примечание: Когда я перехожу к домашнему просмотру, появляется имя пользователя и другие жизненно важные данные. Я предполагаю, что это связано с тем, что в этот момент база данных обновляется, и я могу начать считывать значения.
struct VitalsHeaderView: View {
@EnvironmentObject var session: SessionStore
var body: some View {
VStack {
if session.isLoggedIn {
Text(session.userSession!.username)
.font(.system(size: 20, weight: .bold))
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color(#colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)))
}
}
.padding(.top, 30)
.padding(.leading, 30)
}
}
Ниже вы видите плохой хак, который не работает, но это что-то вроде того, что я хочу сделать. Как я могу использовать очередь отправки для обновления пользовательского интерфейса?
struct VitalsHeaderView: View {
@EnvironmentObject var session: SessionStore
@ObservedObject var signUpViewModel = SignUpViewModel()
func updateUI() {
DispatchQueue.main.asyncAfter(deadline: .now() 2) {
self.session.isLoggedIn = true
}
}
var body: some View {
VStack {
if session.isLoggedIn {
Button(action: updateUI) {
Text(session.userSession!.username)
.font(.system(size: 20, weight: .bold))
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color(#colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)))
}
}
}
.padding(.top, 30)
.padding(.leading, 30)
}
}
ОБНОВЛЕНО
Вот мой SessionStore
код
import Foundation
import Combine
import Firebase
class SessionStore: ObservableObject {
@Published var isLoggedIn: Bool = UserDefaults.standard.bool(forKey: "isLoggedIn") {
didSet {
UserDefaults.standard.set(self.isLoggedIn, forKey: "isLoggedIn")
}
}
var userSession: User?
var handle: AuthStateDidChangeListenerHandle?
func listenAuthenticationState() {
handle = Auth.auth().addStateDidChangeListener({ (auth, user) in
if let user = user {
print(user.email as Any)
let firestoreUserId = Ref.FIRESTORE_DOCUMENT_USERID(userId: user.uid)
firestoreUserId.getDocument { (document, error) in
if let dict = document?.data() {
guard let decodeUser = try? User.init(fromDictionary: dict) else { return }
DispatchQueue.main.async {
self.userSession = decodeUser
self.isLoggedIn = true
}
}
}
} else {
self.isLoggedIn = false
self.userSession = nil
}
})
}
func logout() {
do {
try Auth.auth().signOut()
} catch {
}
}
func unbind() {
if let handle = handle {
Auth.auth().removeStateDidChangeListener(handle)
}
}
deinit {
unbind()
}
}
Я инициализирую VitalsHeaderView
в ProfileView
, который является структурой выше VitalsHeaderView
.
struct ProfileView: View {
@EnvironmentObject var session: SessionStore
@ObservedObject var profileViewModel = ProfileViewModel()
@ObservedObject var signUpViewModel = SignUpViewModel()
var body: some View {
ZStack {
Color(#colorLiteral(red: 0.9058823529, green: 0.9254901961, blue: 0.968627451, alpha: 1)).edgesIgnoringSafeArea(.all)
ZStack(alignment: .top) {
Color(#colorLiteral(red: 0.9058823529, green: 0.9254901961, blue: 0.968627451, alpha: 1))
.clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
.edgesIgnoringSafeArea(.bottom)
ScrollView(.vertical, showsIndicators: false) {
VStack {
ProfileHeaderView(signUpViewModel: signUpViewModel)
VitalsHeaderView(signUpViewModel: signUpViewModel)
ShareProfileView(profileViewModel: profileViewModel)
}
.padding(.top, 30)
}
}
}
.navigationBarHidden(true)
.navigationBarTitle("")
}
}
ПРИМЕЧАНИЕ: я только что добавил (и протестировал) добавление свойства signUpViewModel в представление заголовка Vitals и по-прежнему ничего
Комментарии:
1. Не могли бы вы также добавить свой код для хранилища сеансов и как вы инициализируете свой
VitalsHeaderView
?2. Вам нужно убедиться, что
SessionStore
это соответствует протоколу, а такжеisLoggedIn
является@Published
переменной.3. @Zorayr готово.
SessionStore
соответствуетObservableObject
. Это то, что вы подразумеваете под протоколом? Кроме того,isLoggedIn
это действительно@Published
свойство.