Я работаю над приложением SwiftUI, которое использует AWS Amplify / Cognito для своей аутентификации. Я создал объект сеанса, который отслеживает, аутентифицирован ли пользователь. Этот объект сеанса является ObservableObject, который загружается в environmentObject и доступен для различных представлений. У него есть свойство @Published, которое называется isLoggedIn. В этом объекте сеанса был создан прослушиватель для регистрации изменений в состоянии аутентификации, которые обновляют значение isLoggedIn. Код компилируется и выполняется должным образом, но при попытке обновить свойство isLoggedIn при входе пользователя в систему генерируется следующее предупреждение:
Публикация изменений из фоновых потоков не допускается;Обязательно публикуйте значения из основного потока (через операторы, такие как receive (on :)), при обновлении модели.
Мой вопрос заключается в том, как правильно записать состояние аутентификации и установить значение такто есть он публикуется через механизм environmentObject SwiftUI? Могу ли я переместить мой слушатель в AppDelegate и оттуда обновить сеанс, содержащийся в environmentObject? Если да, то как вы получаете доступ к environmentObjects за пределами представлений? Есть ли другой более чистый способ получения значения и его введения в объекты SwiftUI environmentObjects? Я знаю, что могу сделать вызов API для Cognito / Amplify, чтобы определить состояние аутентификации пользователя, но это не вписывается в реактивную модель SwiftUI или, по крайней мере, я не вижу, как это вписать :).
Ниже показан код, участвующий в этом процессе. Первый фрагмент кода предназначен для объекта Session. Второй показывает объект сеанса, помещаемый в объект enviromentObject в SceneDelegate. Последний фрагмент показывает представление, где объект, если к нему обращаются, чтобы принять решение о рендеринге.
Session.swift
class Swift:ObservableObject {
@Published var firstName: String = ""
@Published var lastName: String = ""
@Published var isLoggedIn: Bool = false
init(){
AWSMobileClient.default().addUserStateListener(self) { (userState, info) in
switch (userState) {
case .guest:
self.isLoggedIn = false
case .signedOut:
self.isLoggedIn = false
case .signedIn:
self.isLoggedIn = true
case .signedOutUserPoolsTokenInvalid:
self.isLoggedIn = false
case .signedOutFederatedTokensInvalid:
self.isLoggedIn = false
default:
self.isLoggedIn = false
}
}
}
SceneDelegate.swift
...
let currentSession = Session()
let mainTabView = MainTabView().environmentObject(currentSession)
...
Представление
struct MyView: View {
@EnvironmentObject var currentSession: Session
var body: some View {
VStack{
if (self.currentSession.isLoggedIn) {
Spacer()
Text("Logged In Content")
Spacer()
}
else{
LoginJoinView()
}
}
}
}