【发布时间】:2016-11-04 05:29:56
【问题描述】:
这个问题要求在以下情况下的最佳实践:
附件是显示我的工作订单和服务核心数据实体的图像。请注意,删除规则当前是对工单无操作。 (注意更改为 Nullify 不会解决我的问题,只会导致同样的问题)。另请注意,在服务上我对 id 有限制。这将不允许重复。因此,我在下面添加了一个合并策略:
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
合并策略将采用我发送的新数据并覆盖数据库中的默认数据。没有这个,我的程序会抛出一个错误。
如果我使用这些设置运行我的代码,并且我对工单但不是服务进行批量删除(因为我想保留这些),那么当我重新启动程序时会发生什么,当我尝试添加时它会崩溃 * *对具有相同 ID 的服务的引用。
我的问题是它为什么会崩溃,解决这个问题的最佳方法是什么?我目前的理论是这些实体可能有另一个唯一标识符,并且因为我删除了工作订单,所以它的引用是到不同的上下文版本的服务......当我使用与旧服务相同的 id 创建新服务时,它可能假定相同的内部 id。我不确定这是否正在发生或如何确认。
我的代码发生在我的一个控制器的 viewDidLoad 方法中,如下所示。
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
let context = gm_getContext()
//Create default fetch request to get all workorders
let fetchRequest: NSFetchRequest<Workorders> = Workorders.fetchRequest()
do{
//Run fetch request to get search results.
let searchResults = try context.fetch(fetchRequest)
//If no results were found and demo mode = true, lets create some default records.
if(searchResults.count<=0 && g_demoMode==true){
print("create default data")
//Uncomment the following lines if you want to prove that the Merge Policy
//Is working for Unique Constraints.
let serviceFetchRequest: NSFetchRequest<Service> = Service.fetchRequest()
let serviceSearchResults = try context.fetch(serviceFetchRequest)
print("Services Count = \(serviceSearchResults.count)")
//First we have to create a sample service
let entity = NSEntityDescription.entity(forEntityName: "Service", in: context)
let service = NSManagedObject(entity: entity!, insertInto: context)
service.setValue(1, forKey: "id")
service.setValue("Tire Repair Service Sample", forKey: "name")
service.setValue("<html>Test Service Field</html>",forKey:"templatedata")
//add reference to the global
g_services.append(service as! Service)
//Proof that service is indeed a Service object and stored in global
print("g_services[0].name = "+g_services[0].name!)
//Save the service object (overwriting an old one with same id if needed)
do {
try context.save()
print("Saved context with service")
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
} catch {
print("Could not save, unknown error")
}
//Now create 3 sample work orders all using the same service template.
let workorderEntity1 = NSEntityDescription.entity(forEntityName: "Workorders", in: context)
let workorder1 = NSManagedObject(entity: workorderEntity1!, insertInto: context)
print("created work order variable 1")
workorder1.setValue(1, forKey: "id")
workorder1.setValue("11402 Kensington Rd, Los Alamitos, CA, 90720", forKey: "address")
workorder1.setValue("33.797472", forKey: "lat")
workorder1.setValue("-118.084136", forKey: "lng")
workorder1.setValue(15,forKey: "client_id")
workorder1.setValue("Need to fix their tire fast", forKey: "desc")
workorder1.setValue("(562)810-4384", forKey: "phone")
workorder1.setValue(g_services[0], forKey: "service")
print("Created first work order")
let workorderEntity2 = NSEntityDescription.entity(forEntityName: "Workorders", in: context)
let workorder2 = NSManagedObject(entity: workorderEntity2!, insertInto: context)
workorder2.setValue(2, forKey: "id")
workorder2.setValue("17078 Greenleaf Street, Fountain Valley, CA, 92708", forKey: "address")
workorder2.setValue("33.714992", forKey: "lat")
workorder2.setValue("-117.958874", forKey: "lng")
workorder2.setValue(16,forKey: "client_id")
workorder2.setValue("This guy does not know what he wants", forKey: "desc")
workorder2.setValue("(562)777-3344", forKey: "phone")
workorder2.setValue(g_services[0], forKey: "service")
let workorderEntity3 = NSEntityDescription.entity(forEntityName: "Workorders", in: context)
let workorder3 = NSManagedObject(entity: workorderEntity3!, insertInto: context)
workorder3.setValue(3, forKey: "id")
workorder3.setValue("17045 South Pacific Avenue", forKey: "address")
workorder3.setValue("33.713565", forKey: "lat")
workorder3.setValue("-118.067535", forKey: "lng")
workorder3.setValue(17,forKey: "client_id")
workorder3.setValue("Tire damaged by the beach", forKey: "desc")
workorder3.setValue("(714)234-5678", forKey: "phone")
workorder3.setValue(g_services[0], forKey: "service")
//Don't need signature, pictures and videos because they just don't exist yet.
//add reference to the global
g_workOrders.append(workorder1 as! Workorders)
g_workOrders.append(workorder2 as! Workorders)
g_workOrders.append(workorder3 as! Workorders)
print("Preparing to save to context for work orders")
//Save the work order objects (overwriting any old ones with same id if needed)
do {
try context.save()
print("Saved context with workorders")
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
} catch {
print("Could not save, unknown error")
}
}else{
print("WorkOrders Count = \(searchResults.count)")
let workorderFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Workorders")
//let workorderFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Workorders")
let deleteWorkOrderRequest = NSBatchDeleteRequest(fetchRequest: workorderFetchRequest) //Deletes ALL workorders
//Perform Actual Deletion On Database Tables
do{
try context.persistentStoreCoordinator!.execute(deleteWorkOrderRequest, with: context)
}catch{
fatalError("Bad Things Happened \(error)")
}
print("deleted workorders")
}
} catch {
print("Error with request: \(error)")
}
print("service table view controller loaded")
}
用于跟踪 coreData 值的上下文和全局变量在 globals.swift 文件中全局定义,如下所示。
var g_workOrders = [Workorders]()
var g_services = [Service]()
//Shortcut method to get the viewcontext easily from anywhere.
func gm_getContext () -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
//For unique constraints it will overwrite the data.
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
return context
}
我尝试过的其他注意事项和事情:
我知道它在这一行崩溃(workorder1.setValue(g_services[0], forKey: "service")),这就是我知道它与服务相关的方式,并且将规则更改为 cascade delete 用于工作订单修复了崩溃但是它删除了服务依附于它!...这是有道理的,但不是我想要的。
【问题讨论】:
标签: swift core-data swift3 ios10 nsfetchrequest