#ios #core-data #ios5 #nsfetchedresultscontroller #icloud
#iOS #основные данные #ios5 #nsfetchedresultscontroller #icloud
Вопрос:
Мое приложение использует только одно managedObjectContext
и настроено на синхронизацию изменений coredata с iCloud, и я использую NSFetchedResultsController
его для извлечения данных для моего UITableView
. Проблема возникает, когда я пытаюсь отредактировать (изменить порядок) ячеек таблицы.
Представьте себе этот сценарий:
Я выполняю [tableView setEditing:YES animated:YES];
Я удерживаю палец на строке и начинаю перемещать его по tableView
(изменить порядок). Тем временем я удаляю строку в приложении Mac и сохраняю изменения.
Приложение iOS узнает о новых изменениях, и я fetchedResultsController
пытаюсь вызвать [tableView beginUpdates]
… и удалить строку из tableView
, пока она редактируется.
Я не знаю, должно ли это работать таким образом, но он выходит из строя.
Как бы вы попытались решить эту проблему?
Журнал:
***[3758:707] asynchronously added persistent store!
***[3758:707] numberOfRowsInSection:3
***[3758:707] numberOfRowsInSection:2
***[3758:707] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-1912.3/UITableView.m:1046
***[3758:707] CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)
***[3758:707] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM insertObject:atIndex:]: index 2 beyond bounds [0 .. 0]'
Первые два журнала находятся в методе раздела — (NSInteger) TableView:(UITableView *) TableView numberOfRowsInSection:(NSInteger) и регистрируют то, что я возвращаю. Я обнаружил, что в первый раз я вернул 3, а во второй раз это было 2!
РЕДАКТИРОВАТЬ: И теперь я думаю… должно ли это работать таким образом, или я должен найти другой способ сделать это? Что должно произойти, когда вы перетаскиваете ячейку и вызываете [TableView moveRowAtIndexPath:toIndexPath:]; ?
Комментарии:
1. Вы говорите, он выходит из строя? Забавно, вы не вставили никакой информации, относящейся к сбою.
Ответ №1:
Ваш сбой говорит о том, что вы запустили -beginUpdates
блок, удалили строку, а затем вызвали -endUpdates
, но когда tableview запросил у своего источника данных количество строк в этом разделе, оно было возвращено 3
, когда ожидалось 2
. Похоже, вы неправильно обновляете свой источник данных.
Комментарии:
1. все данные из TableView извлекаются из fetchedResultsController.fetchedObjects, поэтому их следует обновить… и как я уже писал … numberOfRowsInSection: вызывается 2 раза. В первый раз я возвращаю 3, а во второй раз возвращаю 2.
2. @Kukosk: вы не возвращаете 2. В исключении очень четко указано, что количество строк в разделе 0
3
указано после обновления, когда оно должно быть2
.3. но да, я делаю, и я уверен, что делаю, потому что я помещаю NSLog(); в метод numberOfRowsInSection: … и он вызывается 2 раза… я на 100% уверен, что регистрирую то, что возвращаю…
Ответ №2:
Даже при регистрации что-то происходит. Я имею в виду, что он ломается, поэтому он, очевидно, работает неправильно, верно? Некоторые идеи:
- Возможно, метод, который вы используете для возврата numberOfRowsInSection, настроен неправильно.
- Возможно, cellForRowAtIndexPath ошибочно просматривает неправильный список.
- Возможно, вы удаляете и обновляете отображение в цикле for.
В вашей ошибке явно указано, что он пытается найти элемент с индексом 2 .. в какой-то момент. Почему это выглядит, можно догадаться без исходного кода. У меня были некоторые проблемы с этими вещами, и в конце концов это всегда была моя вина. Трудоемкий, но довольно надежный способ выяснить это — загрузить кучу инструкций NSLog, чтобы вы могли отслеживать, когда вызывается get. Я бы предположил, что вы удаляете объект из массива в неправильное время. И очень легко совершить ошибку.