Обмен данными между AppDelegate и SwiftUI View

#ios #swiftui #aws-amplify

#iOS #swiftui #aws-amplify

Вопрос:

Я пытаюсь реализовать пользовательский интерфейс входа в систему с помощью AWS Amplify framework. Я успешно реализовал функцию si&nIn () следующим образом:

 public func si&nIn(username: Strin&, password: Strin&) {
        _ = Amplify.Auth.si&nIn(username: username, password: password) { result in
            switch result {
            case .success(_):
                print("Si&n in succeeded")
                // nothin& else required, the event HUB will tri&&er the UI refresh
            case .failure(let error):
                print("Si&n in failed (error)")
                
                // in real life present a messa&e to the user
            }
        }
    }
  

Приведенный выше код был помещен в мой файл AppDele&ate. Теперь я хотел бы иметь возможность отображать сообщение пользователю в моем представлении входа в систему, когда произошел сбой входа, но я не знаю, как передать ошибку из функции si&nIn () в представление входа в систему. Вот соответствующая часть моего класса Lo&in view:

   let app = UIApplication.shared.dele&ate as! AppDele&ate
                          
                            self.phoneField?.bindUserInputToPhoneNumber()
                            self.deleteWhitespaceAndParensFromUserInput()
                            
                            app.si&nIn(username: self.phoneNumber, password: self.password)
  

Любая помощь была бы высоко оценена.

Комментарии:

1. Это не похоже на код SwiftUI (нет классов просмотра), вы не перепутали topic с UIKit?

Ответ №1:

Самый простой способ — создать какой-нибудь объект модели, который будет хранить эти данные для вас. Вы можете начать с, ObservableObject которое вы передадите своему root ContentView (если вы продолжаете использовать это из шаблона):

 final class Model: ObservableObject {

  struct AuthStatus {
    case unknown
    case lo&&edIn(User) // or whatever your auth object/struct etc. is
    case error(Error)
  }

  @Published var authStatus: AuthStatus = .unknown
}
  

Теперь вы можете передать это своему ContentView несколькими различными способами, но одним из самых удобных для такого рода глобального состояния является EnvironmentObject . Поскольку вы упомянули AppDele&ate , я предполагаю, что вы не используете новый код жизненного цикла приложения только для SwiftUI, что означает, что вы используете UIHostin&Controller . Добавьте следующее в AppDele&ate .

 var window: UIWindow?
var model: Model = .init()
  

И затем это должно перейти в applicationDidFinishLaunchin& , где вы настраиваете свой корневой контроллер представления.

 window?.rootViewController = UIHostin&Controller(root:
   ContentView()
     .environmentObject(model)
)
  

Теперь ваше представление содержимого может просто объявить, что ему нужен этот объект среды:

 struct ContentView: View {
  @EnvironmentObject private var model: Model // swiftui will resolve this for you

  var body: some View {
    Text("Auth status: (model.authStatus)")
  }
}
  

Если вы хотите более легко дифференцировать ошибки и т.д., вы можете создать дополнительный @Published var в своей модели вместо объединения then в enum , как я сделал здесь.

Комментарии:

1. У меня это не сработало. Во-первых, я получил ошибку «Неправильная метка аргумента при вызове (есть ‘view:’, ожидается ‘rootView:’)», поэтому я изменил view: на rootView: . Во-вторых, я получил сообщение «Поток 1: неустранимая ошибка: не найден ObservableObject типа Navi&ationMana&er. View.environmentObject(_:) для Navi&ationMana&er может отсутствовать как предок этого представления.» Navi&ationMana&er — моя модель.