我有两个实体,它们之间有一对多的关系,基本上一张票据上可以有许多产品,如下所示:Bill Entity和Product Entity。
他们的班级:
extension Bill {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Bill> {
return NSFetchRequest<Bill>(entityName: "Bill")
}
@NSManaged public var id: UUID?
@NSManaged public var name: String?
@NSManaged public var date: Date?
@NSManaged public var products: NSSet?
public var unwrappedID: UUID {
id ?? UUID()
}
public var unwrappedName: String {
name ?? "Unknown Bill Name"
}
public var unwrappedDate: Date {
date ?? Date.now
}
public var formattedDate: String {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "pt_BR")
formatter.timeZone = TimeZone(identifier: "GMT-3")
formatter.dateFormat = "EEEE, MMM d, yyyy, HH:mm"
return formatter.string(from: unwrappedDate)
}
public var productsArray: [Product] {
let set = products as? Set<Product> ?? []
return set.sorted {
$0.unwrappedName < $1.unwrappedName
}
}
}
// MARK: Generated accessors for has
extension Bill {
@objc(addHasObject:)
@NSManaged public func addToProducts(_ value: Product)
@objc(removeHasObject:)
@NSManaged public func removeFromProducts(_ value: Product)
@objc(addHas:)
@NSManaged public func addToProducts(_ values: NSSet)
@objc(removeHas:)
@NSManaged public func removeFromProducts(_ values: NSSet)
}
extension Bill : Identifiable {
}
以及
extension Product {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Product> {
return NSFetchRequest<Product>(entityName: "Product")
}
@NSManaged public var id: UUID?
@NSManaged public var name: String?
@NSManaged public var quantity: Int32
@NSManaged public var price: Double
@NSManaged public var bill: Bill?
public var unwrappedId: UUID {
id ?? UUID()
}
public var unwrappedName: String {
name ?? "Unknown product name"
}
}
extension Product : Identifiable {
}
当我想创建或删除一个对象时,视图(列表)通常会刷新,下面是我用来完成此操作的函数
private func addBill () {
withAnimation {
let bill = Bill(context: managedObjectContext)
bill.id = UUID()
bill.name = billName
bill.date = Date.now
try? managedObjectContext.save()
billName = ""
hideKeyboard()
isShowing = false
}
}
func deleteBill (offsets: IndexSet) {
for offset in offsets {
let bill = bills[offset]
managedObjectContext.delete(bill)
}
try? managedObjectContext.save()
}
private func addProduct () {
withAnimation {
let product = Product(context: managedObjectContext)
product.id = UUID()
product.name = productName
product.price = Double(productPrice) ?? 0.0
product.quantity = 1
product.bill = selectedBill
product.bill?.id = selectedBill.id
product.bill?.date = selectedBill.date
product.bill?.name = selectedBill.unwrappedName
try? managedObjectContext.save()
productName = ""
hideKeyboard()
isShowing = false
}
}
private func deleteProduct (offsets: IndexSet) {
for offset in offsets {
let product = selectedBill.productsArray[offset]
managedObjectContext.delete(product)
}
try? managedObjectContext.save()
}
我的问题发生在我试图更新产品的数量时。我有一个特定的视图称为计数器,它有一个加号按钮和一个减号按钮,当我点击它们时,核心数据会发生变化,但视图不会刷新,只有当我返回祖先视图并再次打开os产品列表时,我才能看到视图中的变化。
这是我的计数器类
struct CounterView: View {
// MARK: - PROPERTIES
@Environment(\.managedObjectContext) var managedObjectContext
@State var selectedProduct: Product
var body: some View {
HStack {
Button(action: {
selectedProduct.quantity += 1
try? self.managedObjectContext.save()
}, label: {
Image(systemName: "plus")
.foregroundColor(comandinhaGold)
.frame(width: 25, height: 25)
})
.buttonStyle(BorderlessButtonStyle())
Text("\(selectedProduct.quantity)")
Button(action: {
if selectedProduct.quantity > 1 {
selectedProduct.quantity -= 1
}
try? self.managedObjectContext.save()
}, label: {
Image(systemName: "minus")
.foregroundColor(comandinhaGold)
.frame(width: 25, height: 25)
})
.buttonStyle(BorderlessButtonStyle())
}
}
}
我使用fetchrequest获取帐单列表,选择帐单后,我将按此方式列出产品
List {
ForEach(selectedBill.productsArray, id: \.id) { product in
HStack (spacing: 16){
VStack(alignment: .leading, spacing: 5) {
Text(product.unwrappedName)
.foregroundColor(comandinhaGold)
.font(.headline)
Text("Preço un.: \(String(format: "R$ %.2f", product.price))")
.font(.footnote)
}
Spacer()
CounterView(selectedProduct: product)
}
}
.onDelete(perform: deleteProduct)
}
我尝试过使用以下命令强制视图刷新
@State var refresher = false
func updateView {
refresher.toggle()
}
和其他类似的解决方案,似乎都不起作用。
尝试@Binding、@StateObject,但没有任何东西真正使带有数量的文本在单击按钮时更新为新值。
1条答案
按热度按时间oalqel3c1#
SwiftUI
在区分引用类型和值类型方面非常严格。@State
和@Binding
仅适用于值类型。另一方面,
NSManagedObject
是一个引用类型,但幸运的是它符合ObservableObject
,引用类型的等价物是@StateObject
和@ObservedObject
。所以简单的替换
与
@State
是错误的,在 *value类型的世界 * 中,它应该是@Binding
。