WWDC 2019
确实包含iOS的新内容以及TableViews
和CollectionView
的新数据源,即UITableViewDiffableDataSource
。
我已经成功地将上述新数据源与Core数据集成在一起,删除并插入了新记录,并且没有任何问题,但是不幸的是,我在将项目从一个部分移到另一个时遇到了问题,如果我尝试将其移动到另一个该部分的最后一个单元格。
下面是我的代码:
表格视图设置
private func setupTableView() {
diffableDataSource = UITableViewDiffableDataSource<Int, Reminder>(tableView: remindersTableView) { (tableView, indexPath, reminder) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(withIdentifier: "SYReminderCompactCell", for: indexPath) as! SYReminderCompactCell
var reminderDateString = ""
let reminderTitle = "\(reminder.emoji ?? "") \(reminder.title ?? "")"
if let date = reminder.date {// check if reminder has date or no , if yes check number of todos and if date in today
let dateFormatter = SYDateFormatterManager.sharedManager.getDateFormaatter()
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .short
reminderDateString = dateFormatter.string(from: date)
}
let toDosList = SYCoreDataManager.sharedManager.fetchAllToDosToOneReminder(reminder: reminder)
cell.indexPath = indexPath
cell.showMoreDelegate = self
cell.initializeToDosCompactView(toDoList: toDosList ?? [],reminderTitleText: reminderTitle,reminderDateText: reminderDateString)
cell.changeTextViewStyle(isChecked: reminder.isCompleted)
return cell
}
setupSnapshot(animated: true)
}
使用表格视图数据创建NSDiffableDataSourceSnapshot
private func setupSnapshot(animated: Bool) {
diffableDataSourceSnapshot = NSDiffableDataSourceSnapshot<Int, Reminder>()
for (i , section) in (fetchedResultsController.sections?.enumerated())! {
diffableDataSourceSnapshot.appendSections([i])
let items = section.objects
diffableDataSourceSnapshot.appendItems(items as! [Reminder])
diffableDataSource?.apply(self.diffableDataSourceSnapshot, animatingDifferences: animated, completion: nil)
}
}
NSFetchedResultsControllerDelegate
用于部分和行
func controller(_ controller:
NSFetchedResultsController<NSFetchRequestResult>, didChange
anObject: Any, at indexPath: IndexPath?, for type:
NSFetchedResultsChangeType,
newIndexPath: IndexPath?) {
switch type {
case .insert:
if let indexPath = newIndexPath {
let section = fetchedResultsController.sections![indexPath.section]
self.diffableDataSourceSnapshot.appendItems(section.objects as! [Reminder], toSection: indexPath.section)
self.diffableDataSource?.apply(self.diffableDataSourceSnapshot, animatingDifferences: true)
}
break
case .update:
break
case .delete:
if let indexPath = indexPath {
guard let item = self.diffableDataSource?.itemIdentifier(for: indexPath) else { return }
self.diffableDataSourceSnapshot.deleteItems([item])
self.diffableDataSource?.apply(self.diffableDataSourceSnapshot, animatingDifferences: true)
}
break
case .move:
if let indexPath = indexPath {
guard let item = self.diffableDataSource?.itemIdentifier(for: indexPath) else { return }
self.diffableDataSourceSnapshot.appendSections([indexPath.section])
self.diffableDataSourceSnapshot.deleteItems([item])
self.diffableDataSource?.apply(self.diffableDataSourceSnapshot, animatingDifferences: true)
}
if let newIndexPath = newIndexPath {
let section = fetchedResultsController.sections![newIndexPath.section]
// let items = fetchedResultsController.object(at: indexPath)
print("snapppp" , diffableDataSourceSnapshot.sectionIdentifiers)
let items = section.objects as! [Reminder]
self.diffableDataSourceSnapshot.appendItems(items, toSection: newIndexPath.section)
self.diffableDataSource?.apply(self.diffableDataSourceSnapshot, animatingDifferences: true)
}
break
}
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
switch type {
case .insert:
setupSnapshot(animated: false)
break
case .update:
break
case .delete:
let section = self.diffableDataSourceSnapshot.sectionIdentifiers[sectionIndex]
self.diffableDataSourceSnapshot.deleteSections([section])
self.diffableDataSource?.apply(self.diffableDataSourceSnapshot, animatingDifferences: true)
//setupSnapshot(animated: false)
break
case .move:
break
}
}
答案 0 :(得分:9)
要顺利使用Core Data,必须将数据源声明为
UITableViewDiffableDataSource<String,NSManagedObjectID>
在setupTableView
中,将闭包参数标签重命名为
(tableView, indexPath, objectID) -> UITableViewCell? in
并通过以下方式获得提醒
let reminder = self.fetchedResultsController.object(at: indexPath)
或
let reminder = try! self.managedObjectContext.existingObject(with: objectID) as! Reminder
然后替换整个方法
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
didChange anObject: Any,
at indexPath: IndexPath?,
for type: NSFetchedResultsChangeType,
newIndexPath: IndexPath?) { ... }
和
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int,
for type: NSFetchedResultsChangeType) { ... }
与
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
self.diffableDataSource.apply(snapshot as NSDiffableDataSourceSnapshot<String, NSManagedObjectID>, animatingDifferences: true)
}
还删除方法setupSnapshot
,则不需要。调用performFetch
之后,并且在管理对象上下文中进行任何更改后,框架都会正确创建快照并调用委托方法。