Проблемы прокрутки с UITextFields в ячейках в Objective-C для iPhone

У меня следующая проблема: у меня есть UITableView с 7 пользовательскими ячейками. Каждая из этих ячеек содержит метку и UITextField. Поскольку ячейки довольно большие, вам нужно прокрутить вниз, чтобы увидеть последние 3 ячейки. Проблема в том, что как только я прокручиваю вниз, текст в текстовых полях первых 3 ячеек (тех, которые тогда не видны) удаляется. Остается только заполнитель. То же самое касается последних 3 ячеек, как только я прокручиваю вверх. Текстовое поле в 4-й ячейке прекрасно сохраняет свой текст, поскольку оно всегда видно. Кто-нибудь знает, как решить эту проблему?

С наилучшими пожеланиями.

ОБНОВЛЕНИЕ: вот код соответствующего комментария:

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

NewXYZTableCell *cell = (NewXYZTableCell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil){
    NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NewXYZTableCell" owner:nil options:nil];

    for(id currentObject in topLevelObjects)
    {
        if([currentObject isKindOfClass:[NewXYZTableCell class]])
        {
            cell = (NewXYZTableCell *)currentObject;
            break;
        }
    }
}

switch (indexPath.row) {            
    case 0:
        cell.myLabel.text = @"XYZ";
        // and so on... 
    default:
        break;
}   
return cell;}

person zhar    schedule 22.10.2010    source источник
comment
Покажите свой метод cellForRowAtIndexPath.   -  person    schedule 22.10.2010


Ответы (2)


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

И это, вероятно, также то, что происходит с вами. Ваши ячейки прокручиваются за пределы экрана и теперь могут свободно использоваться новыми ячейками, появляющимися на экране (отображающими другое содержимое). Таким образом, у вас будет другой заголовок и другое (новое) текстовое поле. Поэтому вам нужно где-то сохранить ввод, если ячейка прокручивается за пределы экрана. Например, вы можете прослушать файл UITextFieldTextDidChangeNotification.

Зарегистрируйте свой контроллер в качестве наблюдателя, например. в -viewDidLoad: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldChanged:) name:UITextFieldTextDidChangeNotification object:textField]

А затем реализуйте свой метод, в данном случае textFieldChanged:, который принимает NSNotification* в качестве параметра и сохраняет ваш ввод:

-(void)textFieldChanged:(NSNotification *)notification {
    ...
}

Не забудьте повторно вставить ввод в свои ячейки, если они прокручиваются назад на экране.

Другой вариант — не использовать удаление из очереди и создавать все ячейки, как только они потребуются. Это может быть лучшей идеей, если у вас очень мало ячеек. Затем вам нужно позаботиться о том, чтобы вернуть правильную ячейку в -cellForRowAtIndexPath:.

person Björn Marschollek    schedule 22.10.2010
comment
Спасибо за этот быстрый, а также полезный ответ. Я уже хранил текстовые значения (но без NotificationCenter; это не лучшая идея для того, чего я хочу достичь), но не подумал об идее снова заполнить текстовые поля этими значениями, когда они появятся в поле зрения экрана. Поскольку ячеек всего 7, какой подход будет быстрее? Повторно заполнять или не использовать удаление из очереди? - person zhar; 22.10.2010
comment
Имея всего семь ячеек, и если это фиксированное число, вероятно, будет быстрее выделить и сохранить все из них в памяти, даже если некоторые из них в данный момент не отображаются. Вы не столкнетесь с проблемами памяти, но при этом будете иметь к ним быстрый доступ. - person Björn Marschollek; 22.10.2010
comment
По неизвестным причинам проблема всегда одна и та же, независимо от того, что я пытаюсь. Я разместил исходный код выше. Не могли бы вы дать мне подсказку в том, как выполнить задачу распределения? Заранее спасибо! - person zhar; 22.10.2010

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

Мое предложение состоит в том, чтобы сохранить семь ячеек в семи переменных экземпляра и создать соответствующие геттеры. Итак, в вашем файле .h вы объявляете переменные:

NewXYZTableCell *cell0;
...
NewXYZTableCell *cell6;

В вашей реализации напишите геттер:

-(NewXYZTableCell*) getCellNumber:(int)cellNumber {
    NewXYZTableCell *cell;
    switch (cellNumber)
    {
        case 0:
            cell = cell0;
            break,

        ...

        case 6:
            cell = cell6;
            break,
    }

    if (cell == nil){
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NewXYZTableCell" owner:nil options:nil];

        for(id currentObject in topLevelObjects)
        {
            if([currentObject isKindOfClass:[NewXYZTableCell class]])
            {
                cell = (NewXYZTableCell *)currentObject;
                break;
            }
        }
    }
    return cell;
}

Этот геттер вернет ячейку с соответствующим номером после ее создания, если ее раньше не было. Затем вы можете использовать его в -tableView:cellForRowAtIndexPath::

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    return [self getCellNumber:indexpath.row];
}
person Björn Marschollek    schedule 22.10.2010
comment
Мне пришлось сделать кое-что еще, прежде чем я смог проверить ваше решение. На самом деле ничего не работало, поэтому я закончил тем, что пополнил ячейки. Спасибо большое. - person zhar; 30.12.2010