我有两张桌子:一张有所有员工的清单,另一张有能够提供某项服务的员工清单(即按摩)。
数据模型如下所示:
每个服务都可以有许多员工提供它,每个员工都可以提供许多服务(多对多关系)。
问题是每次我将员工从Employee List
拖放到Employee providing this service
时,我从最后一个索引开始时得到结果重复,而当我从第一个索引开始时一切正常。
当我再次加载viewController时(即使没有再次启动应用程序),所有数据都会正确显示。
这里代码:
在EmployeesAvailableTableViewController.swift
我初始化NSFetchedResultsController
func initializeFetchedResultsController() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.managedObjectContext
let request: NSFetchRequest<Employee>
request = NSFetchRequest(entityName: "Employee")
//this predicate show only those employee who don't have the entity `service` yet.
request.predicate = NSPredicate(format: "SUBQUERY(service, $c, $c.service_id == %@).@count == 0", (service?.service_id!)!)
let lastNameSort = NSSortDescriptor(key: "lastName", ascending: true)
request.sortDescriptors = [lastNameSort]
fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController?.delegate = self
do {
//I added this as suggested in another question on stackoverflow but nothing has changed
if (self.fetchedResultsController?.fetchedObjects == nil){
try fetchedResultsController?.performFetch()
}
} catch {
fatalError("Failed to initialize FetchedResultsController: \(error)")
}
}
每个单元格都有一个gestureRecognizer,将此方法作为目标:
func didLongPressCell (gr: UILongPressGestureRecognizer) {
let eventCell:EmployeeCell = gr.view as! EmployeeCell
switch gr.state {
case .began:
// other code not relevant .....
case .changed:
// other code not relevant .....
case .ended:
onDragEnded(employeeCell:eventCell)
default:
print("Any other action?")
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.reloadData()
}
func onDragEnded(employeeCell:EmployeeCell){
mDraggableEmployeeCell?.removeFromSuperview()
CoreDataManager.sharedInstance.saveEmployeeServiceRelationship(employeeId: (employeeCell.employee?.employeeId)!, service_id: (service?.service_id)!)
let detailsNC = splitViewController?.viewControllers[1] as! UINavigationController
let details = detailsNC.topViewController as! PriceListViewController
// I am also using controllerWillChangeContent in the other tableView
details.assignedEmployeeTableView.reloadData()
}
在CoreDataManager.swift
中是我保存关系的地方
func saveEmployeeServiceRelationship(employeeId: Int32, service_id:String){
let context = getContext()
var employee:Employee?
var service:Service?
let employeeFetchRequest:NSFetchRequest<Employee> = NSFetchRequest(entityName: "Employee")
employeeFetchRequest.predicate = NSPredicate(format:"employeeId = %d", employeeId )
let serviceFetchRequest:NSFetchRequest<Service> = NSFetchRequest(entityName: "Service")
serviceFetchRequest.predicate = NSPredicate(format:"service_id = %@", service_id )
do {
let employeeResult = try context.fetch(employeeFetchRequest)
let serviceResult = try context.fetch(serviceFetchRequest)
if employeeResult.count > 0 {
employee = employeeResult[0]
}
if serviceResult.count > 0 {
service = serviceResult[0]
}
//set relationship
service?.addToEmployee(employee!)
do {
try context.save()
} catch let error {
print(error)
}
}catch let err {
print(err)
}
}
最后这是我在PriceListViewController
func initializeFetchedResultsController() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.managedObjectContext
context.stalenessInterval = 0
let request: NSFetchRequest<Employee>
request = NSFetchRequest(entityName: "Employee")
request.predicate = NSPredicate(format: "ANY service.service_id == %@", (service?.service_id)!)
let lastNameSort = NSSortDescriptor(key: "lastName", ascending: true)
request.sortDescriptors = [lastNameSort]
fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController?.delegate = self
do {
if (self.fetchedResultsController?.fetchedObjects == nil)
{
try fetchedResultsController?.performFetch()
}
} catch {
fatalError("Failed to initialize FetchedResultsController: \(error)")
}
}
//both this delegates methods get called
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.assignedEmployeeTableView.reloadData()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.assignedEmployeeTableView.reloadData()
}