我正在尝试构建一个带有核心数据的购物车我创建了3个对象来建模我的数据Product,Quantity和CartItem,它包含产品和数量,我将它们保存为核心数据中的可转换对象。
我为我的xcdatamodeld创建了一个具有CartItem属性的类
@objc(CartItemContainer)
class CartItemContainer: NSManagedObject {
@NSManaged var cartItemAttribute: CartItem
}
我正在保存核心数据而没有任何问题,但每当我尝试使用下面的代码更新数量时它不会改变它仍然是1。
static func changeQuantity(product: Product) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<CartItemContainer>(entityName: "CartItemContainer")
var results: [CartItemContainer] = []
do {
results = try context.fetch(fetchRequest)
if let productToChangeQuantityOn = results.first(where: {$0.cartItemAttribute.product.productID == product.productID}) {
let oldQuantity = productToChangeQuantityOn.cartItemAttribute.quantity.value
productToChangeQuantityOn.cartItemAttribute.quantity.value = oldQuantity + 1
try context.save()
context.refresh(productToChangeQuantityOn, mergeChanges: false)
}
}
catch {
print("error executing fetch request: \(error)")
}
}
我已经尝试更新它而不调用context.refresh(productToChangeQuantityOn, mergeChanges: false)
它会在运行时更改数量,但是当重新启动应用程序时,数量仍然是1。
我在这里错过了什么?
任何形式的帮助将不胜感激。
更新:以下是我设置产品的方法。数量和CartItem具有相同的设置。
class Product: NSObject, NSCoding, Decodable {
let productID: String
let category: String
let images: Dictionary<String, String>
let name: Dictionary<String, String>
let price: Dictionary<String, String>
func encode(with aCoder: NSCoder) {
aCoder.encode(productID, forKey: "productID")
aCoder.encode(category, forKey: "category")
aCoder.encode(images, forKey: "images")
aCoder.encode(name, forKey: "name")
aCoder.encode(price, forKey: "price")
}
required init?(coder aDecoder: NSCoder) {
self.productID = aDecoder.decodeObject(forKey: "productID") as! String
self.category = aDecoder.decodeObject(forKey:"category") as! String
self.images = aDecoder.decodeObject(forKey: "images") as! Dictionary<String, String>
self.name = aDecoder.decodeObject(forKey: "name") as! Dictionary<String, String>
self.price = aDecoder.decodeObject(forKey: "price") as! Dictionary<String, String>
}
}
欢迎来到艾哈迈德的核心数据。我很高兴你得到它的工作。在您开始之前,我想建议一个更传统的数据模型,从长远来看,这可能会更好地为您服务。不需要转换.
从广义上讲,原因在Apple的Core Data Programming Guide第一页中列出了核心数据的11个特征,列为要点。通过使用可转换属性而不是关系,我会说你只是完全意识到第一和第五个要点的优点。
关于您的特定设计,我假设同一产品可以在许多购物车中。通过给CartItem
提供可转换类型的产品属性,必须以某种方式在每个购物车中复制相同的产品。如果要更改产品的属性,请在设计中找到包含此产品的所有购物车并更改每个产品。使用传统设计,您只需更改Product对象即可。您的设计需要更多代码(总是很糟糕),而您的用户设备将使用更多资源并且执行代码的速度会变慢。
最后但同样重要的是,您不希望其他工程师在查看您的代码或数据模型时摸不着头脑。:)您希望能够从Apple文档,教程,博客文章,stackoverflow答案和示例代码中学习在互联网上找到。如果您以非传统方式进行操作,则这些资源不适用。
可转换属性是不可变类型,因此无法更改。更改它们的唯一方法是创建一个新对象并将其再次保存到核心数据。
为了解决这个问题,我从我的xcdatamodel中删除了属性cartItemAttribute,它将产品和数量都保存为一个可转换属性。我将其替换为transformable类型的product属性和Int类型的quantity属性,现在一切正常。
这是我更新的代码
static func changeQuantity(product: Product) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<CartItemContainer>(entityName: "CartItemContainer")
do {
let results = try context.fetch(fetchRequest)
if let productToChangeQuantityOn = results.first(where: {$0.product.productID == product.productID}) {
let oldQuantity = productToChangeQuantityOn.quantity
productToChangeQuantityOn.quantity = oldQuantity + 1
try context.save()
context.refresh(productToChangeQuantityOn, mergeChanges: false)
}
}
catch {
print("error executing fetch request: \(error)")
}
}