I am trying to put all my database operations to the background. For on function I need to get a setting back.
if let showMessage = dataManager.getSetting(key: "showWelcomeMessage", modelContext: modelContext) {
if showMessage == "true" {
showWelcomeMessage = true
} else {
showWelcomeMessage = false
}
}
The func in DataManager is:
func getSetting(key: String) -> String? {
let task = Task {
await DataActor.shared.getSetting(key: key)
}
// return await task.value
}
The DataManager is a convenience class for me to access a @ModelActor DataActor which does the lookup.
func getSetting(key: String) -> String? {
do {
let predicate = #Predicate<Setting> { object in
object.key == key
}
var descriptor = FetchDescriptor(predicate: predicate)
descriptor.fetchLimit = 1
let object = try modelContext.fetch(descriptor)
if let setting = object.first {
// print("Found setting \(key) with value \(setting.value)")
return setting.value
}
} catch {
debugPrint("Failed to get object: \(error)")
}
return nil
}
Is there an easy way to retrieve this String in the View as seen in the first code snipped?
Assuming showWelcomeMessage
is a @State
, and that the first code snippet is in a View
, you can put the code in a .task { ... }
modifier. Then you can just await
the getString
call. You should not get the string synchronously.
SomeViewContent()
.task {
if let showMessage = await DataActor.shared.getSetting(key: key) {
showWelcomeMessage = showMessage == "true"
}
}
This will be run when the view first appears. If you also want to run it at a later time, use .task(id: someTrigger) { ... }
. The task will be run again when someTrigger
changes.