如何在 swiftUI 中重新加载视图

问题描述 投票:0回答:1

我正在开发自动登录功能,在应用程序打开时,会运行 cloudkit 查询来确定该设备是否具有已知的用户信息,并将该信息加载到我的模型类中。

这是代码:

维诺应用程序

struct vinoApp: App {
//    @StateObject private var dataController = DataController()
    @ObservedObject var model = Model()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onAppear(perform: {
                    Task {
                        do{
                            try await loadActiveUser()
                        }
                        catch {
                            print("Error: \(error)")
                        }
                    }
                })
        }
    }
    
    private func loadActiveUser() async throws {
        let record = try await queryUserRecord()
        if record != [] {
            //this line works
            model.activeUser = try await UserObj(ckrecord: record[0])
            model.userDoesntExist = false
        }
        else { model.activeUser = UserObj() }
    }
    
    /**
     Queries Account Info from private 'AccountInformation' Record Zone
     
     What does this mean?: Passing argument of non-sendable type 'NSPredicate' outside of main actor-isolated context may introduce data races
     */
    private func queryUserRecord() async throws -> [CKRecord] {
        let cloudDB = CKContainer.default().publicCloudDatabase
        let device = UIDevice.current.identifierForVendor
        
        //set pred
        let pred = NSPredicate(format: "LastKnownDevice == %@", device!.uuidString)
        print(device!.uuidString)
        let query = CKQuery(recordType: "AccountInfo", predicate: pred)
        //query public record
        let (userResults, _) = try await cloudDB.records(matching: query)
        //return the public CKRecord of the user
        return userResults.compactMap { _, result in
            guard let record = try? result.get() else { return nil }
            return record
        }
    }
}

内容视图

struct ContentView: View {
    //State vars
    @ObservedObject var model = Model()
    
    var body: some View {
        VinoMainView()
        /**
         when app is opened we must evaluate if a user exists
         if user exists : model.userDoesntExits = false
         else : model.userDoesntExits = true
         */
            .fullScreenCover(isPresented: $model.userDoesntExist, content: {
                NavigationStack {
                    ZStack {
                        LoginForm()
                        NavigationLink(
                            "Dont Have an Account? Sign-Up Here",
                            destination: SignUpView(
                                userNotSignedin: $model.userDoesntExist
                            )
                        )
                            .font(.custom("DMSerifDisplay-Regular", size: 15))
                            .padding([.top], 300)
                        //Add loading view here?
                    }
                }
            })
        }
    /**
     check if user exists in privateDB zone
     -also sets active user to the user found
     */
    func checkIfUserDoesntExists() -> Bool {
        //if the array of CKRecords returned by 'queryUserRecords()' is not empty -> userDoesntExist = false
        if model.activeUser.isEmpty() {
            //create UserObj from record[0] because the private account zone queried from should only have one record
            //MARK: need to reload views
            return true
        }
        else { return false }
    }
}

型号

class Model: ObservableObject {
    @Published var activeUser = UserObj()
    @Published var userDoesntExist = true
}

我知道实际的查询正在工作,因为当我调试它时,我可以在调试器中看到如下结果:

我可以看到

model.userDoesntExist
也发生了变化,如下所示:

尽管我可以看到代码大部分都在工作,但

fullScreenCover
中的
ContentView
仍然显示,所以我想知道如何刷新
ContentView
以使全屏覆盖在
model.userDoesntExist
消失后消失设置为 false。

ios swift swiftui cloudkit
1个回答
0
投票

在 SwiftUI 中,您将 async/await 与

.task
修饰符 sp 一起使用,您不再需要
onAppear
ObservableObject
。例如

struct vinoApp: App {

    @State var config = Config()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .task {
                    do{
                        config.error = nil
                        config.user = try await loadActiveUser()
                    }
                    catch {
                        print("Error: \(error)")
                        config.error = error
                    }
                }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.