我正在使用NSFetchedResultsController。我无法找到任何简单的教程,为Swift 3
介绍它。
所以这就是我到目前为止所做的。我已经使用NSFetchedResultsController
成功填充了我的表,该orderPosition
从核心数据中提取插入的数据。我在我的核心数据模型中创建了一个名为Int32
的属性,该属性声明为func
。关于在插入时向核心数据添加和保存数据,我没有对此属性做任何事情。
在我初始化NSFetchedResultsController
的fetch let sortDescriptor = NSSortDescriptor(key: "orderPosition", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
中,我修改了排序描述符以包含以下代码:
tableView
然后我实现了func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
attemptFetch()
var objects = self.controller.fetchedObjects!
self.controller.delegate = nil
let object = objects[sourceIndexPath.row]
objects.remove(at: sourceIndexPath.row)
objects.insert(object, at: destinationIndexPath.row)
var i = 0
for object in objects {
object.setValue(i += 1, forKey: "orderPosition")
}
appdel.saveContext()
self.controller.delegate = self
}
func:
didChange
在我.insert
anObject func的实现中,我包含了.delete
,.update
,.move
和.move
的switch-case。
我的case.move:
if let indexPath = indexPath {
tableView.deleteRows(at: [indexPath], with: .fade)
}
if let indexPath = newIndexPath {
tableView.insertRows(at: [indexPath], with: .fade)
}
break
案例如下所示:
Participant Age Type
John 5 A
John 3 B
John 3 B
John 3 C
John 4 B
Amy 5 A
Amy 3 A
Amy 4 C
Amy 4 B
请帮我解决这个问题。我花了几周时间试图理解这一点。我已经经历了很多(如果不是全部)堆栈溢出问题。我从一个实现了一些循环思想,因为我有一个类似的思考过程来解决这个问题,但它没有起作用。没有我遇到的Swift 3核心数据教程/视频,这将真正帮助我解决和理解这一点。我不想放弃这个。
答案 0 :(得分:3)
Swift偏离C,因为=,+ =和其他类似赋值的操作返回i
。因此,您的行var i = 0
for object in objects {
i += 1
object.setValue(i, forKey: "orderPosition")
}
将for (i, object) in objects.enumerated() {
object.setValue(i, forKey: "orderPosition")
}
设置为一个,但始终将该位置设置为0.请尝试改为:
FlowPane
或者如果您想稍微简化代码
ScrollPane
答案 1 :(得分:1)
四处走动:
var objects = frc.fetchedObjects!
// Disable fetchedresultscontroller updates.
let obj objects.remove(at: indexPath.item)
objects.insert(obj, at: newIndexPath)
for (i, obj) in objects.enumerated() {
obj.orderIndex = Int32(i)
}
// Enable fetchedresultscontroller updates.
context.saveContext()
禁用内容是因为tableview已经移动了单元格。如果你然后设置orderIndex,它会尝试再次移动,这可能会像你一样在你身上崩溃。
我的解决方法是没有.move案例
case .update, .move:
print("update")
self.reloadRows(at: [indexPath!], with: .automatic)
我不需要,因为我现在只使用tableview。如果你想让fetchedresultscontroller移动东西,你必须没有这种情况.update,.move但是自己处理.move就像
case .move:
print("move")
self.moveRow(at: indexPath!, to: newIndexPath!)
但不要忘记在下面实施锁定或我的替代方案。
在endUpdates上没有崩溃的另一个解决方法是
if let toIndexPath = newIndexPath {
if type == .update && toIndexPath != indexPath!{
print("it should be a move.")
print("move")
self.moveRow(at: indexPath!, to: newIndexPath!)
return
}
}
检测newIndexPath!= indexPath(旧索引路径)的更新,本质上它会检测未被声明为移动的移动并为我修复问题,但这对我来说太奇怪了。
以下是fetchedresultscontrollers'回答我的orderIndex更改,这应该解释为什么你,如果你想让fetchedresultscontroller移动东西更好地实现我的"移动伪装成更新"在更新对象期间检测或禁用对表的更新,这很好,因为表已经通过移动重新排序了单元格。
from: Optional([0, 2])
to: Optional([0, 1])
update
from: Optional([0, 1])
to: Optional([0, 0])
update
from: Optional([0, 0])
to: Optional([0, 2])
move
... Assertion failure in ...
attempt to perform an insert and a move to the same index path (<NSIndexPath: 0xc000000000400016> {length = 2, path = 0 - 2})
(null)
编辑:
我认为&#34;移动伪装成更新&#34;检测不会产生废话,因为它只是重新加载所有细胞。因此它会将tableviewcell 1次移动到tableview本身+ 3次被检测(无用)。
为什么fetchedresultscontroller使用这个调用模式?它可能会疯狂地尝试按顺序获取表,就像更新来自外部并且表需要更新一样。但它不知道表格单元格已经通过tableview以正确的顺序排列,因此由于某种原因它在super.endUpdates()上崩溃了。
SOO:可能最简单的解决方案是禁用对tableview的更新。怎么样?我现在不知道,我要去睡觉了。
答案 2 :(得分:0)
刚刚在我的项目中实现了类似的功能。变得比看起来更容易。
以下是moveRowAt
方法的更新
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
// NOT NEEDED, SINCE I ASSUME THAT YOU ALREADY FETCHED ON INITIAL LOAD
// attemptFetch()
var objects = self.controller.fetchedObjects!
// NOT NEEDED
//self.controller.delegate = nil
let object = objects[sourceIndexPath.row]
objects.remove(at: sourceIndexPath.row)
objects.insert(object, at: destinationIndexPath.row)
// REWRITEN BELOW
//var i = 0
//for object in objects {
// object.setValue(i += 1, forKey: "orderPosition")
//}
for (index, item) in items.enumerated() {
item.orderPosition = index
}
appdel.saveContext()
//self.controller.delegate = self
}
在didChange
技术上,您不需要任何代码。当您移动项目时,表格会就地更新。保存上下文时,coreData中的数据会更新。因此,下次获取数据时,根据您拥有的sortDescriptor,它将按orderPosition排序。
为我工作。如果您有任何问题,请告诉我。