Индекс NSFetchedResultsController за пределами границ - PullRequest
6 голосов
/ 03 июля 2010

Я использую 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 *tag = [[self.fetchedResultsController fetchedObjects] objectAtIndex:indexPath.row];

I 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];

Если I 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]);
    }
}

Я что-то здесь не так делаю?

Ответы [ 4 ]

17 голосов
/ 10 августа 2012

Я столкнулся с той же проблемой. В моем случае это поврежденный файл кэша. Попробуйте переименовать ваш кеш или позвоните deleteCacheWithName:.

6 голосов
/ 03 июля 2010

Когда вы инициализировали свой контроллер запросов на выборку, вы дали ему 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, и это должно решить вашу проблему.

1 голос
/ 19 ноября 2012

получил эту ошибку прошлой ночью, и это сводило меня с ума. Я обнаружил, что если вы используете раскадровку для указания количества строк и разделов, она должна соответствовать числу, указанному вами в ваших методах источника данных. Чтобы полностью исправить ошибку, вы можете установить все в 0 в инспекторе атрибутов и просто сделать все это программно, или просто убедиться, что методы источника данных и инспектор атрибутов отражают одинаковое количество строк и разделов.

^^

1 голос
/ 03 июля 2010

Компилируете ли вы, нацеливаетесь или тестируете на 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 вы реализовали? Похоже, в вашей реализации может быть как минимум еще одна задерживающаяся ошибка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...