在学习iOS开发的同时,我正在使用Realm Swift构建一个待办事项列表。当我尝试使用coordinator.drop(item.dragItem, toItemAt: destinationIndexPath)对商品进行重新排序时,我的collectionView遇到了问题。
当我包含coordinator时,被拖放的项目首先显示最初位于该索引处的单元格的内容,然后在一段延迟之后被所拖动的单元格的内容所取代。如果我没有包括协调器,那么拖放就会正常工作,并且项目在拖放时会正确地交换(但动画是一个单元格向下缩小到中心并有一点刺耳的动画)。
当我在collectionView中重新排序项目时:
func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) {
if let item = coordinator.items.first,
let sourceIndexPath = item.sourceIndexPath {
do {
try self.realm.write {
// standard category is of type Category
// items is of type List<Task>
standardCategory?.items.remove(at: sourceIndexPath.item)
standardCategory?.items.insert(item.dragItem.localObject as! Task, at: destinationIndexPath.item)
}
} catch {
print("error reording new items, \(error)")
}
coordinator.drop(item.dragItem, toItemAt: destinationIndexPath)
}
}在viewDidLoad()中处理collectionView的更新:
self.notificationToken = tasks!.observe {
(changes: RealmCollectionChange) in
switch changes {
case .initial(_):
self.collectionView.reloadData()
case .update(_, let deletions, let insertions, let modifications):
self.collectionView.performBatchUpdates({
self.collectionView.deleteItems(at: deletions.map({ IndexPath(item: $0, section: 0) }))
self.collectionView.insertItems(at: insertions.map({ IndexPath(item: $0, section: 0) }))
self.collectionView.reloadItems(at: modifications.map({ IndexPath(item: $0, section: 0) }))
}, completion: { status in
self.collectionView.reloadData()
})
case .error(_):
print("error")
}发布于 2019-06-29 16:13:13
我想我现在可以正常工作了。假设边缘情况不会破坏它,下面是答案:
我需要在tasks.observe之外处理模型更新和collectionView更新,以便更准确地控制事件的顺序。您可以使用try realm.commitWrite(withoutNotifying: [notificationToken!])来实现这一点
我认为关键是重新排序删除和更新项的顺序: 1.从模型中删除2.从集合视图中删除3.插入到模型4.使用协调器删除项5.插入到集合视图6.重新加载部分(可选,我认为UI更改需要它)
func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) {
if let item = coordinator.items.first {
if let localObject = item.dragItem.localObject as? Task {
if let sourceIndexPath = item.sourceIndexPath {
do {
try self.realm.write {
standardCategory?.items.remove(at: sourceIndexPath.item)
try realm.commitWrite(withoutNotifying: [notificationToken!])
}
} catch { print("error reording new items, \(error)") }
collectionView.deleteItems(at: [sourceIndexPath])
}
do {
try self.realm.write {
standardCategory?.items.insert(localObject, at: destinationIndexPath.item)
try realm.commitWrite(withoutNotifying: [notificationToken!])
}
} catch { print("error reording new items, \(error)") }
self.collectionView.performBatchUpdates({
coordinator.drop(item.dragItem, toItemAt: destinationIndexPath)
collectionView.insertItems(at: [destinationIndexPath])
}, completion: { status in
let indexSet = IndexSet(integer: destinationIndexPath.section)
collectionView.reloadSections(indexSet)
})
}
}
}解决方案:事实证明,在使用拖放进行排序时不能使用结果(不是100%确定原因,但知道这一点会很好)。以下是使用List的当前工作解决方案:
func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) {
if let item = coordinator.items.first {
if let localObject = item.dragItem.localObject as? Task {
if let sourceIndexPath = item.sourceIndexPath {
self.collectionView.performBatchUpdates({
do {
standardCategory!.realm!.beginWrite()
standardCategory!.items.remove(at: sourceIndexPath.item)
collectionView.deleteItems(at: [sourceIndexPath])
self.standardCategory!.items.insert(localObject as Task, at: destinationIndexPath.item)
coordinator.drop(item.dragItem, toItemAt: destinationIndexPath)
collectionView.insertItems(at: [destinationIndexPath])
try standardCategory!.realm!.commitWrite(withoutNotifying: [notificationToken!])
} catch { print("error reording new items, \(error)") }
}, completion: nil)
}
}
}
}https://stackoverflow.com/questions/56814490
复制相似问题