2013-12-19 25 views
2

如何正確顯示到同一個UITableView中的不同UITableViewCell子類?如何在單個表中使用兩個不同的自定義UITableViewCell子類?

我正在使用這個問題的故事板。我試圖在單個表中使用兩個不同的UITableView單元的子類。 TTTextFieldCell知道如何顯示文本框和TTPickerCell知道如何向用戶展示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行將失敗,因爲它試圖用TTPickerCell對象調用TTTextFieldCell init,並且因爲TTPickerCell對象沒有相同的屬性而失敗。如果我取消對A行和B行的註釋,那麼單元格樣式默認爲UITableViewCellStyleDefault,並且它們不顯示自定義控件。奇怪的是,如果我註釋掉A行,並取消註釋行B,那麼TTTextFieldCells看起來不錯,但TTPickerCells默認爲UITableViewCellStyleDefault

看來,如果我不註冊一個類,出列將返回第一個原型單元類的實例。如果我註冊了課程,那麼單元默認爲UITableViewCellStyleDefault

另外值得注意的是,initWithStyle:reuseIdentifier:選擇器只有在類被註冊時纔會被調用。

那麼,如何正確顯示到同一個UITableView中的不同UITableViewCell子類呢?我必須放棄使用故事板來設計單元格嗎?

預先感謝您。

回答

0

好的,這是我發現的答案。

  1. 不要註冊重用標識符的類。註釋掉A行和B行。
  2. 請勿複製和粘貼原型單元格,除非您非常小心地查看IBOutlet。粘貼的原型單元不關心你分配的UITableViewCell子類,它不會驗證IBOutlets是否存在。

固定#2,一切都很好。

Doh!

-1

我用兩種類型的單元格從NIB和NSMutable陣列加載我的對象,對象有我想在單元格中使用的文本,標題和圖像。在方法cellForRowAtIndexPath ...你把內容從對象到單元格。你可以不用筆尖來初始化。

- (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

您不想在cellForRowAtIndexPath內撥打tableView registerClass:...。相反,你應該一次註冊你的班級/筆尖。這通常在控制器的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; 
} 

編輯:我應該提到dequeueReusableCellWithIdentifier總是從iOS 6中對返回小區。如果你的目標是iOS的早期版本,你甚至需要考慮在這個方法中創建單元格返回nil。

+0

謝謝@亞歷克斯。值得注意的是,這並沒有改變表達的行爲。 :(但它在viewDidLoad方法中註冊很有意義。感謝提示! –

相關問題