Я использую NSFetchedResultsController для экспонатов в моем табличном представлении:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [[self.fetchedResultsController fetchedObjects] count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"TagCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];;
}
Tag *tag = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = tag.name;
return cell;
}
Однако этот код повреждается в этой строке:
Tag *tag = [self.fetchedResultsController objectAtIndexPath:indexPath];
С этим сообщением:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'
У меня есть NSLogged [self.fetchedResultsController fetchedObjects]
и я могу подтвердить, что существуют действительно объекты Тега. Если я заменяю это выше строки с этим, все работает как ожидалось:
Tag *tag = [[self.fetchedResultsController fetchedObjects] objectAtIndex:indexPath.row];
Я NSLogged indexPath
и индексы {0, 0} (разделите 0 строк 0), таким образом, я знаю, что это не проблема с разделом. Я чрезвычайно смущен относительно того, почему это происходит, потому что теоретически, те две части кода делают то же самое. Любая справка ценится.
Спасибо
ОБНОВЛЕНИЯ:
id section = [[[self fetchedResultsController] sections] objectAtIndex:[indexPath section]];
NSLog(@"Section %@", section); <-- returns a valid section
Этот код приводит к тому же исключению: Tag *tag = [[section objects] objectAtIndex:[indexPath row];
Если я NSLog
[section objects]
это возвращает пустой массив. Я не уверен почему [fetchedResultsController fetchedObjects]
возвращает массив с правильными объектами, и [section objects]
возвраты ничто. Это означает, что объекты, которые я создаю, не имеют никакого раздела? Вот код, который я использую для добавления новых объектов:
- (void)newTagWithName:(NSString *)name
{
NSIndexPath *currentSelection = [self.tableView indexPathForSelectedRow];
if (currentSelection != nil) {
[self.tableView deselectRowAtIndexPath:currentSelection animated:NO];
}
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
Tag *newTag = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:self.managedObjectContext];
// Configure new tag
newTag.name = name;
[self saveContext];
NSIndexPath *rowPath = [self.fetchedResultsController indexPathForObject:newTag];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:rowPath] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView selectRowAtIndexPath:rowPath animated:YES scrollPosition:UITableViewScrollPositionTop];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
И вот мой saveContext
метод:
- (void)saveContext
{
// Save changes
NSError *error;
BOOL success = [self.managedObjectContext save:&error];
if (!success)
{
UIAlertView *errorAlert = [[[UIAlertView alloc] initWithTitle:@"Error encountered while saving." message:nil delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil] autorelease];
[errorAlert show];
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
}
Я делаю что-то не так здесь?
Когда вы инициализировали контроллер запроса на выборку, вы дали ему sectionNameKeyPath:
, даже если ваши данные не имеют разделов. Затем вы жестко задали номер раздела таблиц равным 1.
Контроллер запроса на выборку пытается вернуть объект с нулевым индексом раздела в структуре данных, которая вообще не имеет разделов.
Я воспроизвел вашу ошибку в приложении шаблона навигации по умолчанию, изменив sectionNameKeyPath с nil на имя единственного атрибута объекта.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"timeStamp" cacheName:@"Root"];
... а затем изменил
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// return [[fetchedResultsController sections] count];
return 1;
}
, и я получаю:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'
Установите sectionNameKeyPath: nil
, и это должно решить вашу проблему.
Вы компилируете, нацеливаете или тестируете на 3.0?
Что вы получаете от следующего кода:
id section = [[[self fetchedResultsController] sections] objectAtIndex:[indexPath section]];
NSLog(@"Section %@", section);
Вы получаете правильную секцию обратно?
Если да, попробуйте добавить следующую строку:
Tag *tag = [[section objects] objectAtIndex:[indexPath row];
Если это приводит к ошибке, я подозреваю, что проблема в вашем -tableView: numberOfRowsInSection:
и что это может возвращать неправильное количество строк в UITableView
. Не могли бы вы отредактировать свой вопрос и выложить код этого метода?
При дальнейшем рассмотрении я понял, на что указывал TechZen. Вы сообщаете табличному представлению, что у вас есть одна секция, хотя это может быть не так. Далее, вы говорите ему, сколько объектов имеет весь ваш NSFetchedResultsController
, тогда как вам следовало бы ответить на этот вопрос немного более кратко.
Вот небольшое изменение в вашем коде.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[self fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
Внесите эти изменения и посмотрите, какое влияние это окажет.
Какие еще методы UITableViewDataSource
вы реализовали? Похоже, что в вашей реализации может быть как минимум еще одна ошибка.