#iphone #core-data #uitableview
#iPhone #core-data #uitableview
Вопрос:
У меня есть простой UITableViewController, который раньше работал нормально, а теперь что-то сломало его.. Он представляет собой простую форму, которая позволяет мне добавить простую запись из 3 полей в объект, управляемый основными данными.
Когда я добавляю запись, она должна вернуться в таблицу и отобразить содержимое. Я вижу, что он записывает запись в базу данных, но таблица пуста, и появляется ошибка ниже. Я могу продолжать добавлять записи, нажимая на кнопку «Добавить», но каждый раз, когда я сохраняю новую запись и возвращаюсь к таблице, она пуста.
Полная ошибка, которую я вижу, заключается в следующем..
*** Assertion failure in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m:5678
2011-10-01 22:48:11.860 Gradetrack[59617:207] Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath: with userInfo (null)
Если я остановлю симулятор и перезапущу его, я вижу из своих инструкций NSLog, что он обнаружил нужное количество записей из базы данных и попытался загрузить таблицу, но на данный момент я получаю аналогичную ошибку и трассировку стека ниже.
2011-10-01 23:08:50.332 Gradetrack[59795:207] >>> Enumber of courses entered thus far: 4
2011-10-01 23:08:50.334 Gradetrack[59795:207] *** Assertion failure in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m:5678
2011-10-01 23:08:50.337 Gradetrack[59795:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
*** Call stack at first throw:
(
0 CoreFoundation 0x00fd05a9 __exceptionPreprocess 185
1 libobjc.A.dylib 0x01124313 objc_exception_throw 44
2 CoreFoundation 0x00f88ef8 [NSException raise:format:arguments:] 136
3 Foundation 0x000e43bb -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] 116
4 UIKit 0x0035ec91 -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] 883
5 UIKit 0x003544cc -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] 75
6 UIKit 0x003698cc -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] 1561
7 UIKit 0x0036190c -[UITableView layoutSubviews] 242
8 QuartzCore 0x01f70a5a -[CALayer layoutSublayers] 181
9 QuartzCore 0x01f72ddc CALayerLayoutIfNeeded 220
10 QuartzCore 0x01f180b4 _ZN2CA7Context18commit_transactionEPNS_11TransactionE 310
11 QuartzCore 0x01f19294 _ZN2CA11Transaction6commitEv 292
12 UIKit 0x002eb9c9 -[UIApplication _reportAppLaunchFinished] 39
13 UIKit 0x002ebe83 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] 690
14 UIKit 0x002f6617 -[UIApplication handleEvent:withNewEvent:] 1533
15 UIKit 0x002eeabf -[UIApplication sendEvent:] 71
16 UIKit 0x002f3f2e _UIApplicationHandleEvent 7576
17 GraphicsServices 0x01928992 PurpleEventCallback 1550
18 CoreFoundation 0x00fb1944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ 52
19 CoreFoundation 0x00f11cf7 __CFRunLoopDoSource1 215
20 CoreFoundation 0x00f0ef83 __CFRunLoopRun 979
21 CoreFoundation 0x00f0e840 CFRunLoopRunSpecific 208
22 CoreFoundation 0x00f0e761 CFRunLoopRunInMode 97
23 UIKit 0x002eb7d2 -[UIApplication _run] 623
24 UIKit 0x002f7c93 UIApplicationMain 1160
25 Gradetrack 0x00002034 main 102
26 Gradetrack 0x00001fc5 start 53
На основе инструкций NSLog это последняя выполняемая подпрограмма.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
NSLog(@">>> Enteringg %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);
id <NSFetchedResultsSectionInfo> sectionInfo =
[[_fetchedResultsController sections] objectAtIndex:section];
NSLog(@">>> Enumber of courses entered thus far: %d ", [sectionInfo numberOfObjects]);
return [sectionInfo numberOfObjects];
}
Примечание: вывод из количества введенных до сих пор курсов … составил 4, что было правильно.
Здесь я возвращаю ячейки обратно в UITableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath {
NSLog(@">>> Entering %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
[tableView setAllowsSelectionDuringEditing:NO];
[self configureCell:cell atIndexPath:indexPath];
// load the cell with an appropriate image
NSString *path = [[NSBundle mainBundle] pathForResource:@"studentprofile" ofType:@"png"];
UIImage *theImage = [UIImage imageWithContentsOfFile:path];
cell.imageView.image = theImage;
return cell;
}
Основываясь на этих ошибках и моей трассировке стека, кто-нибудь может указать мне правильное направление?
Большое спасибо,
Фил
Ответ №1:
Я только что столкнулся с той же проблемой, но я небрежно объявил:
<UITableViewDelegate, UITableViewDelegate>
вместо того, чтобы правильно:
<UITableViewDelegate, UITableViewDataSource>
Джо
* обновление — я также заметил, что в xCode 4.3 в шаблоне, сгенерированном при создании нового класса UITableViewController, отсутствует ключевой элемент в cellForRowAtIndexPath . Это:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
Комментарии:
1. Я не верю, что вам нужно выделять ячейку табличного представления вручную сейчас, потому что вызов dequeue всегда вернет вам ее обратно (при необходимости она будет создана).
2. Если это правда, должна быть другая проблема. Без добавления этого я получаю сбой. Когда я добавляю это, программа работает нормально. Возможно, это не требуется, если я использую UITableViewController, но в противном случае есть? Я должен продолжить расследование.
3. Мнение @theLastNightTrain неверно. Из документации для dequeueReusableCellWithIdentifier: «Возвращаемое значение объекта UITableViewCell с соответствующим идентификатором или nil, если такой объект не существует в очереди многоразовых ячеек».
4. Мое убеждение основано на использовании раскадровок и iOS 5 с шаблоном ячейки, определенным в TableView — вы запрашиваете ячейку с идентификатором и всегда получаете ее обратно (при условии, что имена идентификаторов совпадают :)).
5. Однако, если вы не используете раскадровки, вам действительно нужно создать ячейку, если отменить очередь… возвращает ноль. Это также устранило проблему, с которой я столкнулся. Хороший улов, @JoeFratianni.
Ответ №2:
Хорошо, извините, предупреждение о сбое.
Я не уверен, как это произошло, но если вы заметили в моем объявлении функции для «cellForRowAtIndexPath»… он просто имеет atIndexPath вместо cellForRowAtIndexPath . Должно быть, я выполнил какой-то опрометчивый глобальный поиск и замену, и это разрушило мой проект.
Сейчас работает. Спасибо.
Вопрос — почему код компилируется без ошибок или предупреждений — Вау — это заняло слишком много времени, чтобы найти.
Комментарии:
1. Привет, Фил, код будет скомпилирован без ошибок или предупреждений, потому что технически вам разрешено создавать метод с помощью «atIndexPath», а не «cellForRowAtIndexPath». Очевидно, что ваш метод «atIndexPath» никогда не будет вызываться UITableViewDelegate, но совершенно законно создавать свой собственный пользовательский метод с этим именем.
Ответ №3:
UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:
Похоже, что вы, возможно, забыли установить идентификатор ячейки при создании экземпляра:
cell = ((DetailCell *)[tableView dequeueReusableCellWithIdentifier:DetailCellIdentifier]);
if (! cell)
{
// build the cell here
}
Если нет, то где в коде вызвана ошибка?
Комментарии:
1. Спасибо. Проверьте это — я отредактировал исходное сообщение, чтобы включить этот фрагмент кода.
Ответ №4:
В моем случае iOS 5.0 ~ 6.0 с раскадровкой должна иметь одинаковый идентификатор ячейки между методом
(- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath) and **storyboard file**.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell"; ... }
Если вы использовали @»Cell» для идентификатора ячейки, следует использовать имя в идентификаторе соответствующей tableViewCell в инспекторе атрибутов файла раскадровки.
Когда вы создаете подкласс файла UITableView, код по умолчанию использует @»Cell», но не storyboard, пустой. Поэтому нужно обратить внимание.
Ответ №5:
Одной из очень распространенных причин этой ошибки является то, что в файле nib представление пользовательского интерфейса верхнего уровня должно иметь тип UITableViewCell, и если это не так, оно выдает эту ошибку утверждения.
Ответ №6:
Я получил это исключение, когда случайно удалил return cell
in tableView:cellForRowAtIndexPath:
. Это исключение возникает, когда ни одна ячейка не создается или не возвращается.
Ответ №7:
Я просто боролся с этим утверждением в течение нескольких часов. Я пытался добавить UIButton в качестве вложенного представления в ячейку, которая также была в указателе. По-видимому, «Autolayout» это не нравится, поэтому после отмены проверки параметра в моем указателе я больше не получаю сбой.