使用异步函数初始化应用程序 | SwiftUI

Posted

技术标签:

【中文标题】使用异步函数初始化应用程序 | SwiftUI【英文标题】:Initialize app with an Async function | SwiftUI 【发布时间】:2021-08-05 14:43:50 【问题描述】:

我需要我的应用程序在启动时配置后端,这是这样做的功能:

// Initializes Amplify
final func configureAmplify() async 
    do 
//            Amplify.Logging.logLevel = .info
        let dataStore = AWSDataStorePlugin(modelRegistration: AmplifyModels())
        let syncWithCloud = AWSAPIPlugin()
        let userAuth = AWSCognitoAuthPlugin()

        try Amplify.add(plugin: userAuth)
        try Amplify.add(plugin: dataStore)
        try Amplify.add(plugin: syncWithCloud)
        try Amplify.configure()
        print("Amplify initialized")
     catch 
        print("Failed to initialize Amplify with \(error)")
    

我尝试将它放在 @main init 中,如下所示:

init() async 
    await networkController.configureAmplify()

但我收到以下错误:

Type 'MyApplicationNameApp' does not conform to protocol 'App'

我尝试在初始化它之后应用建议:

init() 
        

但这似乎很奇怪,所以现在我有 2 个 init。这里发生了什么以及在应用程序启动时初始化多个异步函数的正确方法是什么,例如:

    以上代码(配置放大) 检查用户是否登录 设置会话

注意:init() async 在上面的示例中永远不会被调用,这是该问题中的另一个问题,那么在应用启动时初始化异步函数的正确方法是什么。

【问题讨论】:

不要放在init中,放在.task中。看看来自 WWDC 的 async await 视频 是的,我现在正在浏览整个视频,他们有很多 @loremipsum 【参考方案1】:

使用ViewModifier

.task
    await networkController.configureAmplify()

您可以将 Task 添加到 init,但您可能会遇到问题,因为 SwiftUI 可以根据需要重新创建 View

init()
    Task(priority: .medium)
        await networkController.configureAmplify()
    

或者您可以使用ObservableObject,即@StateObject

使用@StateObject SwiftUI 只会为声明该对象的结构的每个实例创建一次该对象的新实例。

https://developer.apple.com/documentation/swiftui/stateobject

@main
struct YourApp: App 
    @StateObject var networkController: NetworkController = NetworkController()
    
    var body: some Scene 
        WindowGroup 
            ContentView()
        
    

class NetworkController: ObservableObject
    
    init() 
        Task(priority: .medium)
            await configureAmplify()
        
    
    // Initializes Amplify
    final func configureAmplify() async 
        do 
            //            Amplify.Logging.logLevel = .info
            let dataStore = AWSDataStorePlugin(modelRegistration: AmplifyModels())
            let syncWithCloud = AWSAPIPlugin()
            let userAuth = AWSCognitoAuthPlugin()
            
            try Amplify.add(plugin: userAuth)
            try Amplify.add(plugin: dataStore)
            try Amplify.add(plugin: syncWithCloud)
            try Amplify.configure()
            print("Amplify initialized")
         catch 
            print("Failed to initialize Amplify with \(error)")
        
    

【讨论】:

那么我该如何以一种没有问题的方式来实现呢?大声笑这个 API 的初始化非常重要,我不希望我的视图在重新创建后将其关闭。我现在正在看 WWDC 视频,如果我找到更好的选择,我会在这里发布:) 你不能在初始化时,所有的 SwiftUI 都带有这个披露。你最好的选择是使用任务。自定义初始化是视图中的一个麻烦世界。你也可以把它放在一个 ViewModel 类的 init 中,它是一个 ObservableObject 和一个 StateObject 这就是我目前拥有的方式,整个逻辑都在@ObservableObject 中,所以你是说把逻辑放在那里,然后当我点击@main 下的视图时如何初始化它?不是一样的吗? 查看我粘贴的代码。这是不一样的,因为@StateObject 保证每个Apple 只加载一次。不要使用@ObservedObject,它必须是@StateObject 在主视图中传递环境呢? .environmentObject(networkController)我不应该传下去吗?

以上是关于使用异步函数初始化应用程序 | SwiftUI的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 异步数据获取

SwiftUI 和 CloudKit 异步数据加载

在 SwiftUI 视图中结合 onChange 和 onAppear 事件?

在 SwiftUI 应用程序上使用 firebase 数据初始化变量

iOS - SwiftUI - 执行异步操作后导航到下一个屏幕

只有在 SwiftUI 和 Firebase 中完成循环中的异步调用时,如何才能返回函数?