AppDelegate 和 SwiftUI View 之间的通信

Communicating between AppDelegate and SwiftUI View

我正在尝试使用 AWS Amplify 框架实施自定义登录 UI。我已经成功实现了signIn()函数,如下:

public func signIn(username: String, password: String) {
        _ = Amplify.Auth.signIn(username: username, password: password) { result in
            switch result {
            case .success(_):
                print("Sign in succeeded")
                // nothing else required, the event HUB will trigger the UI refresh
            case .failure(let error):
                print("Sign in failed \(error)")
                
                // in real life present a message to the user
            }
        }
    }

以上代码已经放在我的AppDelegate文件中。现在我想做的是在登录失败时在我的登录视图中向用户显示一条消息,但我不知道如何将错误从 signIn() 函数传递到登录视图。这是我登录视图的相关部分 class:

  let app = UIApplication.shared.delegate as! AppDelegate
                          
                            self.phoneField?.bindUserInputToPhoneNumber()
                            self.deleteWhitespaceAndParensFromUserInput()
                            
                            app.signIn(username: self.phoneNumber, password: self.password)

如有任何帮助,我们将不胜感激。

最简单的方法是创建某种模型对象来为您保存这些数据。你可以从一个 ObservableObject 开始,你将传递给你的根 ContentView (如果你继续从模板中使用它):

final class Model: ObservableObject {

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

  @Published var authStatus: AuthStatus = .unknown
}

现在您可以通过几种不同的方式将它传递给您的 ContentView,但是对于这种全局状态来说最好的方法之一是 EnvironmentObject。由于您提到了 AppDelegate,我假设您没有使用新的 SwiftUI only 应用程序生命周期代码,这意味着您正在使用 UIHostingController。在 AppDelegate.

中添加以下内容
var window: UIWindow?
var model: Model = .init()

然后这应该进入 applicationDidFinishLaunching 设置根视图控制器的位置。

window?.rootViewController = UIHostingController(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 变量,而不是像我在这里所做的那样将 then 组合成一个 enum