在 SwiftUI 中更新 CoreData 时更新状态变量
Posted
技术标签:
【中文标题】在 SwiftUI 中更新 CoreData 时更新状态变量【英文标题】:Update State-variable Whenever CoreData is Updated in SwiftUI 【发布时间】:2020-01-28 17:43:30 【问题描述】:从CoreData更新一些数据后,我还想更新一个State
-变量为返回结果的数量。
当 CoreData 发生变化时,Stepper
应该始终设置为返回结果的数量。但是,当我使用Stepper
时,onAppear
也会触发。如何检查 onAppear
是否更改了 CoreData 或使用了 Stepper
?这可能吗?
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】:如果你使用@FetchRequest 和 onReceive numberOfResults 会在发布者发送消息时更新
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")
)
【讨论】:
onAppear
也会在每次更改状态变量时触发。我在 Stepper 中使用状态变量。因此,每当我使用Stepper
时,它都会设置为numberOfResults
。我更改了代码以使其更清晰。您还知道如何使步进器工作吗?
您可以尝试两种方法。但这取决于您是否需要此视图上的 FetchRequest 变量来做其他事情。如果您不需要 FetchRequest 进行其他任何操作,可以使用 init() 期间的一次性 FetchRequest 来设置 numberOfResults 变量。 developer.apple.com/library/archive/documentation/Cocoa/… 如果您确实需要 FetchRequest,我将上面的代码更改为包含一个 initSetup Bool。【参考方案2】:
您不需要@State var numberOfResults
。您可以在 Text()
中仅使用 objects.count
。包装器@FetchRequest
为您完成所有工作。每当您将YourModel
实体对象添加到ManagedObjectContext
中时,它将触发FetchRequest
刷新并为您提供实际结果。 @FetchRequest
已经在做 @State
之类的事情了
【讨论】:
我需要它作为状态变量,因为我在Stepper
中使用了该变量。它最初应该设置为最大值。以上是关于在 SwiftUI 中更新 CoreData 时更新状态变量的主要内容,如果未能解决你的问题,请参考以下文章
使用 CloudKit + CoreData,如何在没有 SwiftUI 的 @FetchRequest 的情况下从远程云更新中更新 UI?
SwiftUI CoreData - 如何更新获取请求和列表
SwiftUI 和 CoreData:将 FetchResults 传递给 DetailView 并更新它们