I’m working on an auto login feature where upon the app opening, a cloudkit query is ran to determine if this device has known user info or not and that info is loaded to my Model class.
Here is the code:
Vino App
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
}
}
}
Content View
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 }
}
}
Model
class Model: ObservableObject {
@Published var activeUser = UserObj()
@Published var userDoesntExist = true
}
I know the actual query is working because when I debug it I can see the results like so in the deugger:

And I can see that model.userDoesntExist gets changed as well, like so:

Even though I can see the code is working for the most part the fullScreenCover in ContentView is still displayed so I’m wondering how to refresh the ContentView to make the full screen cover go away once model.userDoesntExist is set to false.




