Как правильно использовать «dequeueReusableCellWithIdentifier:» с несколькими идентификаторами? - PullRequest
0 голосов
/ 08 ноября 2011

У меня есть табличное представление с базовыми данными, которое показывает список редактируемых полей, для разных типов полей у меня разные UTableViewCells с разными идентификаторами ячеек.Когда я выполняю слишком быструю прокрутку в симуляторе или пытаюсь «отскочить» мимо последней ячейки, я получаю сбой, говоря, что UITableView dataSource должен вернуть ячейку из tableView: cellForRowAtIndexPath .Вся проблема исчезнет, ​​если я удалю dequeueReusableCellWithIdentifier: steps.Что означает, что мое табличное представление менее эффективно.В моем табличном представлении я использую не более 20 извлеченных объектов (больше по 8-10 строк), поэтому неэффективность может быть незначительной проблемой.Я просто хотел бы знать, что я делаю что-то не так.

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

    Field *aField = [self.fetchedResultsController objectAtIndexPath:indexPath];
    static NSString *CellIdentifier = @"Cell";
    static NSString *ChoiceIdentifier = @"ChoiceCell";
    static NSString *SwitchIdentifier = @"SwitchCell";

    UITableViewCell *cell;

    if ([aField.fieldType isEqualToString:@"choice"] || [aField.fieldType isEqualToString:@"date"]  || [aField.fieldType isEqualToString:@"multiChoice"] ) {

        NSLog(@"ChoiceCell");
        cell = [tableView dequeueReusableCellWithIdentifier:ChoiceIdentifier];
        if (cell == nil) {
            if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
                [[NSBundle mainBundle] loadNibNamed:@"ChoiceTableViewCell-iPad" owner:self options:nil];
            } else {
                [[NSBundle mainBundle] loadNibNamed:@"ChoiceTableViewCell" owner:self options:nil];
            }
        }

    } else if ([aField.fieldType isEqualToString:@"boolean"]){

        NSLog(@"SwitchCell");
        cell = [tableView dequeueReusableCellWithIdentifier:SwitchIdentifier];
        if (cell == nil) {

            if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
                [[NSBundle mainBundle] loadNibNamed:@"SwitchTableViewCell-iPad" owner:self options:nil];
            } else {

                [[NSBundle mainBundle] loadNibNamed:@"SwitchTableViewCell" owner:self options:nil];
            }
        }


    } else {

        NSLog(@"Cell");
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
                [[NSBundle mainBundle] loadNibNamed:@"EditableTableViewCell-iPad" owner:self options:nil];
            } else {

                [[NSBundle mainBundle] loadNibNamed:@"EditableTableViewCell" owner:self options:nil];
            }
        }
    } 

    cell = editableCell;
    self.editableCell = nil;


    // Configure the cell...
    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}

Дополнительные сведения: EditableCell устанавливается так же, как в каждом из NIB, соответствующих пользовательским ячейкам.Я попытался более точно установить это, сказав

dynamicCell = [[[NSBundle mainBundle] loadNibNamed:@"ChoiceTableViewCell-iPad" owner:self options:nil] objectAtIndex:0];

, но все еще имел ту же проблему.Он никогда не должен возвращать ноль.Все NIB загружаются, пока я не прокручиваю слишком быстро.Я дважды и трижды проверил имена NIB, чтобы убедиться.

Вот обновленный рабочий код:

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

{

Field *aField = [self.fetchedResultsController objectAtIndexPath:indexPath];
static NSString *CellIdentifier = @"Cell";
static NSString *ChoiceIdentifier = @"ChoiceCell";
static NSString *SwitchIdentifier = @"SwitchCell";


if ([aField.fieldType isEqualToString:@"choice"] || [aField.fieldType isEqualToString:@"date"]  || [aField.fieldType isEqualToString:@"multiChoice"] ) {

    NSLog(@"ChoiceCell");
    dynamicCell = [tableView dequeueReusableCellWithIdentifier:ChoiceIdentifier];
    if (dynamicCell == nil) {
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {


            [[NSBundle mainBundle] loadNibNamed:@"ChoiceTableViewCell-iPad" owner:self options:nil];
        } else {
            [[NSBundle mainBundle] loadNibNamed:@"ChoiceTableViewCell" owner:self options:nil];
        }
    }

} else if ([aField.fieldType isEqualToString:@"boolean"]){

    NSLog(@"SwitchCell");
    dynamicCell = [tableView dequeueReusableCellWithIdentifier:SwitchIdentifier];
    if (dynamicCell == nil) {

        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
            [[NSBundle mainBundle] loadNibNamed:@"SwitchTableViewCell-iPad" owner:self options:nil];
        } else {

            [[NSBundle mainBundle] loadNibNamed:@"SwitchTableViewCell" owner:self options:nil];
        }
    }


} else {

    NSLog(@"Cell");
    dynamicCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (dynamicCell == nil) {
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
            [[NSBundle mainBundle] loadNibNamed:@"EditableTableViewCell-iPad" owner:self options:nil];
        } else {

            [[NSBundle mainBundle] loadNibNamed:@"EditableTableViewCell" owner:self options:nil];
        }
    }
} 

UITableViewCell *cell;
cell = dynamicCell;
self.dynamicCell = nil;


// Configure the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;

}

1 Ответ

4 голосов
/ 08 ноября 2011

Похоже, проблема в:

cell = editableCell

, если editableCell равно нулю, ваше приложение будет аварийно завершено.Я предполагаю, что вы намереваетесь установить editableCell на loadNibNamed:.Не устанавливается, если вы удаляете ячейку из очереди.

...