Ячейка UITableView / данные исчезают

#iphone #objective-c #ios #ipad #uitableview

#iPhone #objective-c #iOS #iPad #uitableview

Вопрос:

У меня есть сегментированный TableView, который загружает все данные во все ячейки всех разделов. В каждой ячейке есть текстовое поле.

Tableview не соответствует экрану iPad полностью, и я не могу получить доступ ко всем невидимым ячейкам для чтения / сохранения данных. И когда я вношу изменения в «Текстовое поле», затем прокручиваю вверх, прокручиваю вниз, все изменения исчезают.

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

Извините, я только начал работать с таблицами несколько дней назад… Я думаю, что эта проблема как-то связана с ячейками многократного использования, но не уверен, как ее решить.

Прошу вашей помощи.

инициализация:

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

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];


    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 400, 30)] ;
        textField.enabled = NO;
        cell.accessoryView = textField;
        [textField release];

}
    UITextField *textField = (UITextField*)cell.accessoryView;

    if(indexPath.section == 0)
        cell.textLabel.text = [idenInfo objectAtIndex:indexPath.row];
    else if (indexPath.section == 1)
        cell.textLabel.text = [prodInfo objectAtIndex:indexPath.row];
    else if (indexPath.section == 2)
        cell.textLabel.text = [visInfo objectAtIndex:indexPath.row];


    if(indexPath.section == 0)
        textField.text = [idenInfoRez objectAtIndex:indexPath.row];
    else if (indexPath.section == 1)
        textField.text = [prodInfoRez objectAtIndex:indexPath.row];
    else if (indexPath.section == 2)
        textField.text = [visInfoRez objectAtIndex:indexPath.row];

    textField = nil;

    return cell;
}
  

Ответ №1:

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

Что вам нужно будет сделать, так это обновить ваш источник данных (то есть idenInfoRez , prodInfoRez и vizInfoRez в вашем случае), когда пользователь изменил значение внутри текстового поля. Итак, вам нужно будет установить свой UIViewController в качестве делегата каждого текстового поля и обновлять значения по мере ввода пользователем.

Комментарии:

1. Как я узнаю, текстовое поле какой ячейки (indexPath) вызвало событие? Значит, я действительно могу изменить соответствующий источник данных?

2. посмотрите на методы протокола UITableViewDataSource. В таблице вы найдете методы, которые необходимо реализовать, чтобы узнать, какой indexPath был изменен действием пользователя. Я бы также немного почитал. В руководстве по программированию приложений для iOS описывается шаблон проектирования MVC. Руководство по программированию контроллера табличного представления — лучшее начало для таблиц.

Ответ №2:

[UIView beginAnimations: контекст @»ShiftUp»: ноль]; [UIView setAnimationDuration:0.0001]; — (UITableViewCell *)TableView: (UITableView *)TableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { раздел NSInteger = [раздел indexPath];

 static NSString *CellIdentifier = @"Cell";

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

если (ячейка == ноль) {

     [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
    cell = objCustCell;
   cell.selectionStyle = UITableViewCellSelectionStyleNone ;
  

}

 if (section == 0) {

       switch (indexPath.row) {
           case 0:{

            cell.lable.text = @"Date of Birth";
            cell.field.placeholder = @"Birth Name";

               break;
           }

           case 1:{

               cell.lable.text = @"Enter Your Name";
               cell.field.placeholder = @"Full Name";

               break;
           }


           default:
               break;
       }

 }

[UIView beginAnimations:@"ShiftUp" context:nil];
[UIView setAnimationDuration:0.0001];

//  [UIView beginAnimations: @"ShiftUp" context:nil];

NSLog(@"Load cellfor raw at index  ");
// Configure the cell.
       return cell;
  

}

Примечание: Анимация UIView не позволит текстовому полю удалять данные, иначе любой UIController останется прежним в своем старом состоянии!! Не фиксируйте анимацию, иначе она не будет работать!!

Ответ №3:

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

 -(IBAction) EditingChanged: (id) sender

{

   UITextField *txt =(UITextField*)sender;

   NSString* str =[[NSString alloc] initWithString: txt.text]; 
   //get current text string

   NSInteger path =[tableView indexPathForSelectedRow].row;
          // get currently selected row, this could be a bit different depending on the number of sections

   [yourMutableArray insertObject: str atIndex: path]; 

   [str release]

}
  

Затем вы можете заполнить TextField значениями из NSMutableArray в любое время, когда ячейки будут воссозданы заново, т.Е.

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

{

   ...... // create the cells here and use viewTag to get the textFields

   textField.text= [yourMutableArray objectAtIndex:indexPath.row];

   //This may be a bit different depending on the number of sections.

}
  

Кроме того, обратите внимание, что было бы целесообразно инициализировать yourMutable массив до емкости, равной количеству ячеек.

Прошу прощения, если коды неправильно отформатированы, поскольку это мой первый пост о stackoverflow — также в коде могут быть некоторые опечатки. Надеюсь, это кому-то поможет.

Ответ №4:

каждый раз, когда мы выделяем ячейку для разных данных, данные не будут перезагружать ячейку, каждый раз, когда данные переопределяют предыдущие данные, перед выделением ячейки для очистки ячейки, например, cell = nil

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

            static NSString *CellIdentifier = @"Cell";
            UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

           cell=nil;
        //it clear data in the cell
            if (cell == nil)
 {
                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
                UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 400, 30)] ;
                textField.enabled = NO;
                cell.accessoryView = textField;
                [textField release];

        }
  

Ответ №5:

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

Удалите это:

 static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];


if (cell == nil) {
  

И просто оставьте это:

    UITableViewCell * cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 400, 30)] ;
    textField.enabled = NO;
    cell.accessoryView = textField;
    [textField release];
  

Это должно быть нормально, если у вас в tableview всего небольшое количество ячеек (примерно менее 50).


Лучшим решением было бы оставить повторное использование ячеек включенным и заполнить их текстовые поля по мере их запроса. Подход отличается от приложения к приложению, но вы в принципе никогда не должны обращаться к ячейкам напрямую и хранить данные ячейки где-то еще, например, в NSArray NSStrings. Затем вы могли бы манипулировать NSArray. Ваш метод cellForRowAtIndexPath будет выглядеть примерно так:

 textField.text = [arrData objectAtIndex:indexPath.row];
  

Комментарии:

1. Если я удалю статическую NSString *cellIdentifier = @»Cell»; Я не смогу выполнить инициализацию с использованием вашего кода. Потому что CellIdentifiel не существует. Если я сохраню это, но удалю «если», проблема не будет решена. (У меня всего 13 ячеек)

2. Просто передайте nil в качестве аргумента. Пожалуйста, обратите внимание, однако, что это сделает ваше табличное представление очень неэффективным, если позже оно будет содержать значительно больше строк, чем текущие 13.

3. Доступ к ячейкам по-прежнему недоступен, и данные по-прежнему перезагружаются после прокрутки.

4. Совершенно неправильный ответ. Вам необходимо правильно обновлять свою модель данных, когда пользователь вносит изменения. Когда вы это сделаете, таблица загрузится правильно.