Вопрос по ios – UITableView cellForRowAtIndexPath вызывается более одного раза для каждой строки

6

Если у меня есть UITableView, в котором есть 4 строки, то не должен ли метод cellForRowAtIndexPath вызываться 4 раза при переходе к этому представлению? Я обнаружил, что он вызывается несколько раз, например, если есть 4 строки, он вызывается 8 раз, когда я углубляюсь в представление UITable, и затем 12 раз, когда я возвращаюсь к тому же UITableView.

Я просто неправильно понимаю, как работает этот метод? Я подумал, что он должен вызываться один раз для каждой отображаемой строки (прокрутка не используется, поскольку содержимое табличного представления легко помещается на экране моего iPad).

Я должен, вероятно, отметить, что UITableView содержится в MasterViewController UISplitViewController на iPad.

РЕДАКТИРОВАТЬ: реальная проблема, которую я получаю, заключается в несоответствии в способе применения следующего кода:

if (selectedNavItem.folder.isAssignedToUser != [NSNumber numberWithInt:1]) 
        {
            NSLog(@"%@", cell.textLabel.text);
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            cell.userInteractionEnabled = NO;
            cell.textLabel.enabled = NO;
            cell.detailTextLabel.text = @"Access not granted";
            cell.detailTextLabel.enabled = NO;
        }

Когда я впервые "разверну" до определенного уровня моего стека навигации все работает как надо. Но позже, если я перемещаюсь назад вверх или вниз, то обнаруживаю, что различные строки обрабатываются неправильно, то есть они в конечном итоге отключаются, когда их нужно включить. Это заставило меня поставить точку останова и некоторый код регистрации, чтобы попытаться выяснить, что происходит. Я обнаружил, что приведенный выше код вызывался больше раз, чем было строк - и значение cell.textLabel.text, которое я регистрировал, не имело смысла - значение для одной и той же строки регистрировалось несколько раз, а другие строки не были быть зарегистрированным вообще.

РЕДАКТИРОВАТЬ: Предоставление некоторого кода по запросу:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"FolderCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}


- (NSFetchedResultsController *)fetchedResultsController
{
    if (__fetchedResultsController != nil) {
        return __fetchedResultsController;
    }

    // Set up the fetched results controller.
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"NavItem" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort keys as appropriate.
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"sortOrder" ascending:YES];
    NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor1, sortDescriptor2, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.
        managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return __fetchedResultsController;
}   

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
    NavItem *selectedNavItem = (NavItem *)managedObject;
    cell.textLabel.text = [[managedObject valueForKey:@"name"] description];
    cell.detailTextLabel.text = @"";

    if (selectedNavItem.folder != nil) {
        cell.imageView.image = [UIImage imageNamed:@"Folder.png"];


        //NSLog(@"%@", selectedNavItem.folder.isAssignedToUser);

        if (selectedNavItem.folder.isAssignedToUser != [NSNumber numberWithInt:1]) 
        {
            NSLog(@"%@", cell.textLabel.text);
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            cell.userInteractionEnabled = NO;
            cell.textLabel.enabled = NO;
            cell.detailTextLabel.text = @"Access not granted";
            cell.detailTextLabel.enabled = NO;
        }
    }
    else if (selectedNavItem.document != nil) {
        cell.detailTextLabel.text  = [[selectedNavItem.document valueForKey:@"itemDescription"] description];

        if ([[selectedNavItem.document.fileName pathExtension] isEqualToString:@"pdf"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"pdf.png"];
        }
        else if ([[selectedNavItem.document.fileName pathExtension] isEqualToString:@"doc"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"docx"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"Word-32x32.png"];
        }
        else if ([[selectedNavItem.document.fileName pathExtension] isEqualToString:@"xls"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"xlsx"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"Excel-32x32.png"];
        }
        else if ([[selectedNavItem.document.fileName pathExtension] isEqualToString:@"ppt"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"pps"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"Powerpoint-32x32.png"];
        }
        else if ([[selectedNavItem.document.fileName pathExtension] isEqualToString:@"mp3"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"wav"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"65-note.png"];
        }
        else if ([[selectedNavItem.document.fileName pathExtension] isEqualToString:@"mp4"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"mov"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"46-movie-2.png"];
        }
        else if ([[selectedNavItem.document.fileName pathExtension] isEqualToString:@"ibooks"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"ibooks-icon.png"];
        }
        else if ([[selectedNavItem.document.fileName pathExtension] isEqualToString:@"png"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"bmp"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"jpg"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"jpeg"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"tif"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"tiff"] || [[selectedNavItem.document.fileName pathExtension] isEqualToString:@"gif"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"41-picture-frame.png"];
        }
        else 
        {
            cell.imageView.image = [UIImage imageNamed:@"179-notepad.png"];
        }


    }
    else if (selectedNavItem.attachment != nil) {
        cell.detailTextLabel.text  = [[selectedNavItem.attachment valueForKey:@"itemDescription"] description];

        if ([[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"pdf"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"pdf.png"];
        }
        else if ([[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"doc"] || [[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"docx"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"Word-32x32.png"];
        }
        else if ([[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"xls"] || [[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"xlsx"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"Excel-32x32.png"];
        }
        else if ([[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"ppt"] || [[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"pps"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"Powerpoint-32x32.png"];
        }
        else if ([[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"mp3"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"65-note.png"];
        }
        else if ([[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"mp4"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"46-movie-2.png"];
        }
        else if ([[selectedNavItem.document.fileName pathExtension] isEqualToString:@"ibooks"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"ibooks-icon.png"];
        }
        else if ([[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"png"] || [[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"bmp"] || [[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"jpg"] || [[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"jpeg"] || [[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"tif"] || [[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"tiff"] || [[selectedNavItem.attachment.fileName pathExtension] isEqualToString:@"gif"]) 
        {
            cell.imageView.image = [UIImage imageNamed:@"41-picture-frame.png"];
        }
        else 
        {
            cell.imageView.image = [UIImage imageNamed:@"179-notepad.png"];
        }
    }

}
Где вы получили количество вызовов вашего метода? yoyosir
Также убедитесь, что вы не звонитеreloadData многократно. Alladinian
Я поместил точку останова в метод cellForRowAtIndexPath и посчитал, сколько раз была достигнута точка останова. daveywc
Я добавил некоторый код по запросу - не уверен, правильно ли я выбрал методы или нет. daveywc
cellForRowAtIndexPath вызывается для каждой ячейки. Можете ли вы поделиться некоторым кодом, чтобы мы могли взглянуть на вашу проблему. Thnx Anshuk Garg

Ваш Ответ

2   ответа
7

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

Или когда выбран или не выбран.
@ Султан, я думаю, что нет. Может быть, вы имеете в виду другой метод - (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath & apos;
Вы неправы. Я точно знаю, что имею в виду. Выбор или отмена выбора ячейки может полностью изменить пользовательский интерфейс ячейки, поэтомуcellForRow  можно назватьfour раз, когда вы выбираете строку.
@Sulthan, но я проверял это только что.
В итоге я обнаружил, что проблема, которую я пытался решить, была вызвана ошибкой в моей логике. Я устанавливал стили для ячеек, которые я хотел отключить, но не всегда устанавливал альтернативный стиль для ячеек, которые я хотел включить. Поэтому в некоторых случаях ячейка, которую я хотел включить, неправильно наследовала настройки для отключенной ячейки, потому что отключенная ячейка была последней обработанной. daveywc
3

Весьма вероятно, что вы звоните из других методов:

UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

self.tableView снаружи- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath вызовет cellForRowAtIndexPath дважды.

Похожие вопросы