Данные из одного сектора дублируются в другой

swift

#1

Всем привет,помогите мне: я создаю новые события в одном viewcontroller и записываю их в coredata (значения: Date, String, Double ) . В tableview я вытягиваю эти события из кордаты, и они сортируются по дням в порядке убывания. Все работало нормально, пока я не захотел сгруппировать их по датам. Я прочитал инструкцию (https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html) и сделал все в соответствии с инструкциями. Но теперь, создавая первое событие (допустим, 1 мая), создается новый сектор, к нему записываются ячейки для этого дня. Но если я создаю новое событие для другого месяца или дня, все данные из 1-го сектора дублируются ко всем ячейкам других секторов. Не могу понять где ошибка.
Выдернул куски кода которые с которыми работаю :

override func viewDidLoad() {
super.viewDidLoad()

let fetchRequest: NSFetchRequest<Events> = Events.fetchRequest()

let sortDescriptor = NSSortDescriptor(key: "date", ascending: false)

fetchRequest.sortDescriptors = [sortDescriptor]


if let context = (UIApplication.shared.delegate as? AppDelegate)?.coreDataStack.persistentContainer.viewContext {


    fetchResaultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: "date", cacheName: nil)

    fetchResaultsController.delegate = self

    do {
        try fetchResaultsController?.performFetch()
        nameEvents = fetchResaultsController.fetchedObjects!
        print("success")
    } catch let error as NSError {
        print(error.localizedDescription)
    }
}

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    tableViewEvents.beginUpdates()
}

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {

    switch type {

    case .insert: guard let indexPath = newIndexPath else {break}
    tableViewEvents.insertRows(at: [indexPath], with: .automatic)

    case .delete: guard let indexPath = indexPath else {break}
    tableViewEvents.deleteRows(at: [indexPath], with: .automatic)


    case .update: guard let indexPath = indexPath else {break}
    tableViewEvents.reloadRows(at: [indexPath], with: .automatic)

    default:
        tableViewEvents.reloadData()
    }

    nameEvents = controller.fetchedObjects as! [Events]
}

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
    switch type {
    case .insert:
        tableViewEvents.insertSections(IndexSet(integer: sectionIndex), with: .fade)
    case .delete:
        tableViewEvents.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
    case .move:
        break
    case .update:
        break
    }
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    tableViewEvents.endUpdates()
}



    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let sectionInfo = fetchResaultsController.sections![section]
        return sectionInfo.numberOfObjects
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return fetchResaultsController.sections!.count }


    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let theSection = fetchResaultsController.sections![section].name

        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZ"
        let date = formatter.date(from: theSection)
        formatter.dateFormat = "MMMM yyyy"

        var formattedDateStr: String? = nil
        if let aDate = date {
            formattedDateStr = formatter.string(from: aDate)
        }
        return formattedDateStr

#3

Если вы хотите сделать секции-месяцы, вам нужно сделать отдельное поле в сущности с названием месяца и указать его в sectionNameKeyPath. NSFetchedResultsController не обладает никаким интеллектом и не способен определить что вы от него хотите)


#4

я создал отдельный атрибут в сущности. sectordate , указал его в sectionNameKeyPath.
в этот атрибут идет дата из события которое будет создаваться.
Все отлично стало отображаться , но теперь как только обновляется таблица , ячейки из нулевого сектора дублируются во другие сектора.


#5

Попробуйте так: https://yadi.sk/d/ZYG-Adkv3WEgRP
Там keypath вида “2018.05”


#6

спасибо, вчера посмотрел ваш код и свой, вроде бы все почти одинаковое , но у вас работает у меня нет. Буду сидеть разбираться, по итогу отпишусь.


#7

Александр выражаю огромную благодарность в помощи. Нашел в чем была причина.
в коде по урокам ивана я добавил пустой массив

var example: [Events] = []

и

var fetchResaultsController: NSFetchedResultsController<Events.>

и присваивал строкам новые данные типа :

cell.moneyCell.text = example[indexPath.row].number

теперь
добавил константу

let item = fetchResaultsController.object(at: indexPath)

и заменил присвоение на :

cell.moneyCell.text = item.number

и все прекрасно работает.
осталось понять как это работает :

fetchResaultsController.object(at: indexPath)

=)))