提问人:Luke Chase 提问时间:8/28/2020 最后编辑:Luke Chase 更新时间:9/2/2020 访问量:137
Swift - 如何调试核心数据关系错误?
Swift - How to debug a core data relationship error?
问:
我正在创建一个产品的核心数据对象,该对象还具有许多其他产品,并且具有多对多关系。
转换我的 json 时,我检查该产品是否有关联的产品,然后添加关系。
if let relatedItems = response["related"] as? [[String:Any]] {
// create the related items
for d in relatedItems {
let related = try createAssociatedFromResponse(response: d)
product.addToAssociatedProducts(related)
try self.managedObjectContext.save()
}
}
这会产生一个不一致的错误 - 由于未捕获的异常“NSInternalInconsistencyException”而终止应用,原因:“对象不应同时修改和添加”
我尝试检查该对象是否已经作为关系存在,但仍然收到此错误。
编辑 - 将 json 转换为核心数据对象的完整代码
func createFromResponse(response: Dictionary<String, Any>) throws -> Product {
let productID = response["id"] as! NSNumber
var product: Product!
let fetchRequest: NSFetchRequest<Product> = Product.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "productID = %@", productID)
if let fetchedProduct = try self.managedObjectContext.fetch(fetchRequest).first {
product = fetchedProduct
} else {
product = (NSEntityDescription.insertNewObject(forEntityName: "Product", into: self.managedObjectContext) as! Product)
product.productID = productID
}
product.name = response["name"] as? String
product.ref = response["ref"] as? String
product.desc = response["description"] as? String
product.imageURL = response["image"] as? String
product.image = nil
product.thumbImageURL = response["thumb"] as? String
product.thumbImage = nil
product.pdfURL = response["pdf"] as? String
product.manufacturerUrl = response["manufacturer_url"] as? String
if let categoriesInHierarchy = response["categories"] as? NSArray
{
if categoriesInHierarchy.count == 3
{
if let topCategory = categoriesInHierarchy[0] as? [String:Any] {
product.topCategoryID = topCategory["id"] as? NSNumber
product.topCategoryName = topCategory["name"] as? String
}
if let subCategory = categoriesInHierarchy[1] as? [String:Any] {
product.subCategoryID = subCategory["id"] as? NSNumber
product.subCategoryName = subCategory["name"] as? String
}
if let bottomCategory = categoriesInHierarchy[2] as? [String:Any] {
product.bottomCategoryID = bottomCategory["id"] as? NSNumber
product.bottomCategoryName = bottomCategory["name"] as? String
}
}
}
if let relatedItems = response["related"] as? [[String:Any]] {
// create the related items
for d in relatedItems {
let related = try createAssociatedFromResponse(response: d)
product.addToAssociatedProducts(related)
}
try self.managedObjectContext.save()
}
return product
}
func createAssociatedFromResponse(response: Dictionary<String, Any>) throws -> Product {
let productID = response["id"] as! NSNumber
var product: Product!
let fetchRequest: NSFetchRequest<Product> = Product.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "productID = %@", productID)
if let fetchedProduct = try self.managedObjectContext.fetch(fetchRequest).first {
product = fetchedProduct
} else {
product = (NSEntityDescription.insertNewObject(forEntityName: "Product", into: self.managedObjectContext) as! Product)
product.productID = productID
}
product.name = response["name"] as? String
product.ref = response["ref"] as? String
product.desc = response["description"] as? String
product.imageURL = response["image"] as? String
product.image = nil
product.thumbImageURL = response["thumb"] as? String
product.thumbImage = nil
product.pdfURL = response["pdf"] as? String
product.manufacturerUrl = response["manufacturer_url"] as? String
if let categoriesInHierarchy = response["categories"] as? NSArray
{
if categoriesInHierarchy.count == 3
{
if let topCategory = categoriesInHierarchy[0] as? [String:Any] {
product.topCategoryID = topCategory["id"] as? NSNumber
product.topCategoryName = topCategory["name"] as? String
}
if let subCategory = categoriesInHierarchy[1] as? [String:Any] {
product.subCategoryID = subCategory["id"] as? NSNumber
product.subCategoryName = subCategory["name"] as? String
}
if let bottomCategory = categoriesInHierarchy[2] as? [String:Any] {
product.bottomCategoryID = bottomCategory["id"] as? NSNumber
product.bottomCategoryName = bottomCategory["name"] as? String
}
}
}
product.associatedProducts = nil
return product
}
答:
0赞
Stamenkovski
8/28/2020
#1
你能在for循环之后移动吗,像这样:try self.managedObjectContext.save()
if let relatedItems = response["related"] as? [[String:Any]] {
// create the related items
for d in relatedItems {
let related = try createAssociatedFromResponse(response: d)
product.addToAssociatedProducts(related)
}
try self.managedObjectContext.save()
}
编辑:
您如何在 ?createAssociatedFromResponse
编辑 2:你不应该在不同的线程中使用,把你的函数包装在块中,就像这样:NSManagedObjectContext
perform
self.managedObjectContext.perform {
if let relatedItems = response["related"] as? [[String:Any]] {
// create the related items
for d in relatedItems {
let related = try createAssociatedFromResponse(response: d)
product.addToAssociatedProducts(related)
}
try self.managedObjectContext.save()
}
}
评论
0赞
Luke Chase
8/28/2020
我已经尝试过了,但我仍然有同样的错误。我现在添加了完整的代码。
0赞
Stamenkovski
8/28/2020
createFromResponse 函数在哪个线程上调用?我想它在后台线程上?
0赞
Luke Chase
9/1/2020
是的,在循环遍历 JSON 响应时会多次调用它
0赞
Stamenkovski
9/2/2020
好的,你应该将核心数据函数包装在 perform 块中。self.managedObjectContext.perform { }
评论