Вы используете NSFetchedResultsController
, поэтому не стоит поддерживать отдельный массив (ваш items
); Просто используйте метод object(at:)
, чтобы получить предмет при необходимости.
У вас также есть проблема, так как вы добавляете элемент в массив items
в cellForRowAt:
- cellForRowAt:
будет вызываться более одного раза для данного indexPath
, и нет гарантии, в каком порядке cellForRowAt:
вызывается (например, при прокрутке таблицы).
Если вы используете NSFetchedResultsController
, вам действительно следует реализовать его делегат и использовать методы делегата для обновления таблицы.
Избавьтесь от массива items
и используйте что-то вроде:
extension ItemsTableViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
let newIndexPath: IndexPath? = newIndexPath != nil ? IndexPath(row: newIndexPath!.row, section: 0) : nil
let currentIndexPath: IndexPath? = indexPath != nil ? IndexPath(row: indexPath!.row, section: 0) : nil
switch type {
case .insert:
self.tableView.insertRows(at: [newIndexPath!], with: .automatic)
case .delete:
self.tableView.deleteRows(at: [currentIndexPath!], with: .fade)
case .move:
self.tableView.moveRow(at: currentIndexPath!, to: newIndexPath!)
case .update:
self.tableView.reloadRows(at: [currentIndexPath!], with: .automatic)
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.tableView.endUpdates()
}
}
Ваш cellForRowAt
должен быть:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "itemsTable", for: indexPath) as! ItemsTableViewCell
let item = fetchedRC.object(at:indexPath)
if item.isComplete == true {
let attributeString = NSMutableAttributedString(string: item.name ?? "")
attributeString.addAttribute(NSAttributedString.Key.strikethroughStyle, value: NSUnderlineStyle.single.rawValue, range: NSMakeRange(0, attributeString.length))
cell.nameL.attributedText = attributeString
} else {
cell.nameL.text = item.name
}
return cell
}
и ваш код удаления должен быть:
if editingStyle == .delete {
context.delete(fetchedRC.object(at:indexPath))
do {
try context.save()
} catch let error as NSError {
print("Could not save. \(error.localizedDescription)")
}
}
Не забудьте назначить self
на fetchedRC.delegate
при создании контроллера выбранных результатов.