使用核心数据的具有多个部分的可扩散数据源

时间:2019-10-22 18:31:21

标签: ios swift ios13 diffabledatasource

WWDC 2019确实包含iOS的新内容以及TableViewsCollectionView的新数据源,即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
    }
}

1 个答案:

答案 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之后,并且在管理对象上下文中进行任何更改后,框架都会正确创建快照并调用委托方法。