Текст метки пользовательской ячейки перекрывается после сохранения основных данных

Я действительно борюсь с этим и надеюсь, что кто-то может помочь.

Я использую Core Data и заполняю TableView с помощью fetchedResultsController. Для типа ячейки я использую Custom. После выбора ячейки, переходящей в подробное представление, я изменяю одно из полей и нажимаю «Сохранить», что возвращает меня в табличное представление. Единственная проблема в том, что старый текст поля все еще там, а новый текст перекрывает его.

В моем tableviewcontroller.m есть следующий код для ячейки:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

        [self configureCell:cell atIndexPath:indexPath];
    }
    else {

        // Cells all appear blank if I don't include the following line
        [self configureCell:cell atIndexPath:indexPath];

        Games *game = [self.fetchedResultsController objectAtIndexPath:indexPath];

        UILabel *nwOpp = (UILabel *)[cell.contentView viewWithTag:401];
        NSLog(@"nwOpp:%@", nwOpp.text);
        nwOpp.text = [NSString stringWithFormat:@"%@", game.opponents.name];

        UILabel *nwDate = (UILabel *)[cell.contentView viewWithTag:501];
        NSLog(@"Date:%@", nwDate.text);
        nwDate.text = [NSString stringWithFormat:@"%@  -  %@" , [dateFormatter stringFromDate: game.date] , game.location];

        UIImageView *nwImg2 = (UIImageView *)[cell.contentView viewWithTag:201];
        nwImg2.image = game.opponents.image;
    }

    return cell;
}

    - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {

    Games *game = [self.fetchedResultsController objectAtIndexPath:indexPath];

    CGRect imageFrame = CGRectMake(70, 2, 20, 20);
    UIImageView *customImage = [[UIImageView alloc] initWithFrame:imageFrame];
    [customImage setContentMode:UIViewContentModeScaleAspectFill];
    customImage.clipsToBounds = YES;
    customImage.image = game.teams.image;
    customImage.tag = 101;
    [cell.contentView addSubview:customImage];

    CGRect imageFrame2 = CGRectMake(230, 2, 20, 20);
    UIImageView *customImage2 = [[UIImageView alloc] initWithFrame:imageFrame2];
    [customImage2 setContentMode:UIViewContentModeScaleAspectFill];
    customImage2.clipsToBounds = YES;
    customImage2.image = game.opponents.image;
    customImage2.tag = 201;
    [cell.contentView addSubview:customImage2];

    CGRect teamFrame = CGRectMake(0, 18, 140, 24);
    UILabel *teamLabel = [[UILabel alloc] initWithFrame:teamFrame];
    teamLabel.font = [UIFont boldSystemFontOfSize:14];
    teamLabel.text = [NSString stringWithFormat:@"%@", game.teams.name];
    teamLabel.textAlignment = NSTextAlignmentCenter;
    teamLabel.tag = 301;
    [cell.contentView addSubview:teamLabel];

    CGRect versusFrame = CGRectMake(140, 18, 20, 24);
    UILabel *versusLabel = [[UILabel alloc] initWithFrame:versusFrame];
    versusLabel.font = [UIFont boldSystemFontOfSize:16];
    versusLabel.text = @"vs";
    versusLabel.textAlignment= NSTextAlignmentCenter;
    [cell.contentView addSubview:versusLabel];

    CGRect oppFrame = CGRectMake(160, 18, 140, 24);
    UILabel *oppLabel = [[UILabel alloc] initWithFrame:oppFrame];
    oppLabel.font = [UIFont boldSystemFontOfSize:14];
    oppLabel.text = [NSString stringWithFormat:@"%@", game.opponents.name];
    oppLabel.textAlignment = NSTextAlignmentCenter;
    oppLabel.tag = 401;
    [cell.contentView addSubview:oppLabel];

    CGRect dateFrame = CGRectMake(10, 40, 300, 12);
    UILabel *dateLabel = [[UILabel alloc] initWithFrame:dateFrame];
    dateLabel.font = [UIFont systemFontOfSize:10];
    dateLabel.text = [NSString stringWithFormat:@"%@  -  %@" , [dateFormatter stringFromDate: game.date] , game.location];
    dateLabel.textAlignment = NSTextAlignmentCenter;
    dateLabel.tag = 501;
    [cell.contentView addSubview:dateLabel];

}

Я использую метод делегата для сохранения изменения данных:

    -(void)EditGameViewControllerDidSave {

    NSError *error = nil;
    NSManagedObjectContext *context = self.managedObjectContext;
    if (![context save:&error]) {
        NSLog(@"Error! %@", error);
    }

    [self.navigationController popViewControllerAnimated:YES];

    [self.tableView reloadData];
}

Изменения FetchedResultsController:

    -(void) controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}

-(void) controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

    UITableView *tableView = self.tableView;

    switch (type) {
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }

}

person TazmanNZL    schedule 21.08.2013    source источник


Ответы (1)


Проблема в том, что вы неправильно используете шаблонный метод configureCell.

Если вы посмотрите на код шаблона Apple, вы заметите, что он используется для настройки полностью созданной ячейки, то есть для заполнения ее данными.

При использовании раскадровки создание ячейки можно в значительной степени опустить. С раскадровкой обычно нет необходимости создавать что-то в if (cell==nil) {...}. Конечно, вы все равно можете сделать это в коде, если не в блоке if, а также в отдельном методе, если хотите. Я бы рекомендовал называть этот метод createCell, а не configureCell.

Затем в configureCell: вы можете ввести свои данные - то, что вы уже делаете за пределами блока if в cellForRowAtIndexPath:. Это фактически то, что входит в configureCell.

Как вы это делаете сейчас, вы создаете новые метки в обратном вызове NSFetchedResultsControllerDelegate при изменении данных. Вы вызываете configureCell в случае NSFetchedResultsChangeUpdate (действительно именно то, что происходит при изменении атрибута), но configureCell создает новые представления и добавляет их в ячейку.

Поэтому просто переместите код создания ячейки из configureCell, а код, заполняющий ячейку данными, в configureCell, и все будет в порядке.

person Mundi    schedule 21.08.2013