2013-12-19 3 views
2

Как правильно отображать различные подклассы UITableViewCell в одном и том же UITableView?Как использовать два разных пользовательских подкласса UITableViewCell в одной таблице?

Я использую раскадровку для этого вопроса. Я пытаюсь использовать два разных подкласса ячейки UITableView в одной таблице. Идея, что TTTextFieldCell s умеет показывать текстовое поле и TTPickerCell s знает, как представить UIPicker пользователю. Там протокол TTTableViewCell определяет один селектор: [setCellDetails (NSDictionary*) cellDetails] Каждый подкласс UITableViewCell знает, что делать с помощью словаря CellDetails для настройки ячейки.

-(NSArray *)tableData { 
    if (!_tableData) { 
      _tableData = 
      @[ // Sections 
      @{ // Section Details 
        kSectionName:@"Scout Information" 
        ,kRows:@[ // Rows 
          @{// Cell Details 
            kBoundProperty:self.scoutName 
            ,kReuseIdentifier:kTextFieldCell 
            ,kLabel:@"Name" 
            ,kPlaceholderValue:@"Scout's Name" 
            } 
          ,@{ 
            kReuseIdentifier:@"TTPickerCell" 
            ,kLabel:@"Type" 
            ,kPlaceholderValue:@"Cadet, Junior, etc..." 
            } 
          ,@{ 
            kBoundProperty:self.yearsScouting 
            ,kReuseIdentifier:kTextFieldCell 
            ,kLabel:@"Years" 
            ,kPlaceholderValue:@"Years of Experience" 
            ,kKeyboardStyle:@(UIKeyboardTypeNumberPad) 
            } 
          ] 
        } 
      ,@{ // Section Details 
        kSectionName:@"Parent Information" 
        ,kRows:@[ 
          @{ 
            kBoundProperty:self.parentName 
            ,kReuseIdentifier:kTextFieldCell 
            ,kLabel:@"Name" 
            ,kPlaceholderValue:@"Parents's Name" 
            } 
          ] 
        } 
      ]; 
    } 
    return _tableData; 
} 


- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 
    // Line A 
    [self.tableView registerClass:[TTTextFieldCell class] forCellReuseIdentifier:@"TTTextFieldCell"]; 
    // Line B 
    [self.tableView registerClass:[TTPickerCell class] forCellReuseIdentifier:@"TTPickerCell"]; 
} 


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSDictionary* cellDetails = self.tableData[indexPath.section][kRows][indexPath.row]; 

    NSString* reuseIdentifier = cellDetails[kReuseIdentifier]; 

    // Line C 
    UITableViewCell<TTTableViewCell> *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier]; 

    [cell setCellDetails:cellDetails]; 
    return cell; 
} 

Теперь, вот вопрос. Если я прокомментирую строки A и B, то TTTextFieldCells отображаются правильно. Но строка C завершится неудачно, потому что она пытается вызвать инициализацию TTTextFieldCell с помощью объекта TTPickerCell и не работает, поскольку объект TTPickerCell не имеет одинаковых свойств. Если я раскомментирую строки A и B, то стили ячейки по умолчанию равны UITableViewCellStyleDefault, и они не отображают пользовательские элементы управления. Как ни странно, если я прокомментирую Line A и раскомментирую строку B, то TTTextFieldCells выглядит великолепно, но TTPickerCells по умолчанию - UITableViewCellStyleDefault.

Похоже, что если я не зарегистрирую класс, dequeue вернет экземпляр первого класса ячеек прототипа. Если я зарегистрирую класс, ячейка по умолчанию будет равна UITableViewCellStyleDefault.

Также обратите внимание, что initWithStyle: reuseIdentifier: селекторы вызываются только при регистрации класса.

Итак, как правильно отображать различные подклассы UITableViewCell в одном и том же UITableView? Должен ли я отказаться от использования раскадровки для создания ячейки?

Заранее спасибо.

ответ

0

Хорошо, это то, что я нашел для себя ответом.

  1. Не регистрируйте класс для повторного использования. Комментируйте строки A и B.
  2. Не копируйте и не вставляйте прототипы ячеек, если вы не проявляете особой осторожности, чтобы просмотреть IBOutlets. Вложенная ячейка прототипа не заботится о том, какой подкласс UITableViewCell вы ее назначаете тоже, она не подтверждает наличие IBOutlets.

Исправлено # 2, и все было хорошо.

Doh!

-1

Я использовал 2 типа ячеек, загруженных из массивов NIB и NSMutable с моими объектами, объекты имеют тексты, заголовки и изображения, которые я хочу использовать в ячейках. В методе cellForRowAtIndexPath ... u помещает контент из объектов в ячейку. U может инициализировать без наконечника.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
     if (your condition){ 
     NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CellClass1" owner:self options:nil]; 
     CellClass1 *cell = (CellClass1 *)[topLevelObjects objectAtIndex:0]; 
     }else{ 
     NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CellClass2" owner:self options:nil]; 
     CellClass2 *cell = (CellClass2 *)[topLevelObjects objectAtIndex:0];} 

     //get your content for cell at array or your own estructure 
     Content *content = [contents objectAtIndex:indexPath.row]; 


     cell.description.text = content.description; 

     return cell; 
    } 
1

Вы не хотите называть tableView registerClass:... внутри cellForRowAtIndexPath. Вместо этого вы должны регистрировать свои классы/nibs один раз. Это часто делается в методе контроллера viewDidLoad. Ваш cellForRowAtIndexPath реализация может выглядеть примерно так:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSDictionary* cellDetails = self.tableData[indexPath.section][kRows][indexPath.row]; 

    NSString *reuseIdentifier = (/*some condition*/ ? @"TTTextFieldCell" : @"TTPickerCell"); 
    UITableViewCell<TTTableViewCell> *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier]; 
    [cell setCellDetails:cellDetails]; 
    return cell; 
} 

EDIT: Я должен упомянуть dequeueReusableCellWithIdentifier всегда возвращает ячейку с прошивкой 6 на. Если вы ориентируетесь на более раннюю версию iOS, вам нужно учитывать создание ячеек даже в том случае, если этот метод возвращает nil.

+0

спасибо @Alex. Стоит отметить, что это не изменило выраженного поведения. :(Но имеет смысл зарегистрироваться в методе viewDidLoad. Спасибо за подсказку! –

Смежные вопросы