问题
After updating some data from CoreData, I also want to update a State
-variable to the number of returned results.
When CoreData is changed, the Stepper
should always be set to the number of returned results. However, onAppear
fires also when I use the Stepper
. How can I check in onAppear
whether CoreData was changed or the Stepper
was used? Is that even possible?
import SwiftUI
struct ContentView: View {
@State var numberOfResults = 0
@FetchRequest(entity: YourModel.entity(), sortDescriptors: [], predicate:NSPredicate(format: "isSelected == %@", NSNumber(booleanLiteral: true))) var objects: FetchedResults<YourModel>
var body: some View{
return VStack{
Stepper("text", value: $numberOfResults, in: 0...objects.wrappedValue.count, step:5)
.onReceive(objects.publisher, perform: {_ in
self.numberOfResults = self.objects.count
print("onReceive")
})
}
}
}
回答1:
If you use @FetchRequest and onReceive numberOfResults will be updated when the publisher sends a message
import SwiftUI
struct DidSetCoreData: View {
@State var numberOfResults = 0
@State var initSetup1: Bool = true
@State var initSetup2: Bool = true
@State var adjustedCount = 0
@FetchRequest(entity: YourModel.entity(), sortDescriptors: [], predicate:NSPredicate(format: "isSelected == %@", NSNumber(booleanLiteral: true))) var objects: FetchedResults<YourModel>
var body: some View{
return VStack{
Text("Total Count= \(objects.count)")
Text("Adjusted Total = \($adjustedCount.wrappedValue)")
//You need the separate adjusted count variable to save the changes
//Option 1 Stepper - Keeps the max step flexible, eliminates the need for the numberOfResults var
Stepper("AdjTotal - FlexibleMax", value: $adjustedCount, in: 0...objects.count, step:5)
.onReceive(objects.publisher.count(), perform: {count in
//onReceive will be called everytime there is a change to objects.count or body refresh
print("onReceive - Option 1")
if self.initSetup1{
//The variable will only be setup once
self.adjustedCount = count
self.initSetup1 = false
print("initSetupComplete - Option 1")
}
})
//Option 2 Stepper
Stepper("AdjTotal - initMax", value: $adjustedCount, in: 0...$numberOfResults.wrappedValue, step:5)
.onReceive(objects.publisher.count(), perform: {count in
//onReceive will be called everytime there is a change to objects.count or body refresh
print("onReceive - Option 2")
if self.initSetup2{
//The variables will only be setup once
self.numberOfResults = count //Limits the max step to only the original count
self.adjustedCount = self.numberOfResults
self.initSetup2 = false
print("initSetupComplete - Option 2")
}
})
//Option 3 Stepper - Limits the StepperMax to the Stepper value
Stepper("AdjTotal - ValueMax", value: $numberOfResults, in: 0...$numberOfResults.wrappedValue, step:5)
.onReceive(objects.publisher.count(), perform: {count in
//onReceive will be called everytime there is a change to objects.count or body refresh
print("onReceive - Option 3")
if self.initSetup3{
//The variable will only be setup once
self.numberOfResults = count
self.initSetup3 = false
print("initSetupComplete - Option 3")
}
})
}
}
}
回答2:
You don't need @State var numberOfResults
. You can use just objects.count
in a Text()
. The wrapper @FetchRequest
do all the work for you. Whenever you add a YourModel
entity object into ManagedObjectContext
, it will trigger FetchRequest
to refresh and give you actual result. @FetchRequest
is already do things like @State
来源:https://stackoverflow.com/questions/59954342/update-state-variable-whenever-coredata-is-updated-in-swiftui