【问题标题】:Many different UITableViewCells in one TableView一个 TableView 中有许多不同的 UITableViewCells
【发布时间】:2012-04-12 02:28:27
【问题描述】:

我有一个NSDictionary,我们会说是这样的:

key:       value:
name       Bookshelf
movies     Array containing: (Movie 1, Movie 2, Movie 3)
books      Array containing: (Book 1, Book 2, Book 3)
music      Array containing: (Music 1, Music 2, Music 3)

等等。现在我要做的是创建一个 tableView 来显示所有这些信息,但根据字典键是不同类型的单元格。比如电影用cellForMovies书用cellForBooks音乐用cellForMusic,每个都有自己的布局。

显然,我过于简单化了,但希望你能理解我想要做什么。

如果我为每个部分做部分和不同的单元格类型,我可以做到这一点,但我不想这样做。我希望能够有这样的表,例如:

cellForBooks
cellForMovies
cellForMovies
cellForMusic
cellForBooks

等等...您可以指出我的任何想法或资源吗?我只关心 iOS 5 支持(故事板)。

使用解决方案编辑:

非常感谢所有提供帮助的人,尤其是 atticus,他完成了最后的工作。

最终的工作是将数据结构更改为字典数组,然后将Key: type Value: book/movie/music 添加到每个条目。数据结构现在看起来像:

Array[0]: Dictionary: [Key: type Value: book], [Key: name Value: Physics];
Array[1]: Dictionary: [Key: type Value: music], [Key: name Value: Rock];

然后配置我这样做的单元格:

NSString *CellIdentifier = @"Cell";
NSDictionary *object = [self.listOfStuff objectAtIndex:indexPath.row];
if ([[object objectForKey:@"type"] isEqualToString:@"book"]){
    CellIdentifier = @"BookCell";
}else if ([[object objectForKey:@"type"] isEqualToString:@"music"]){
    CellIdentifier = @"MusicCell";
}else if ([[object objectForKey:@"type"] isEqualToString:@"movie"]){
    CellIdentifier = @"MovieCell";
}

每一个在故事板中都有一个不同的 tableviewcell。我们发现如果您想使用任何内置单元格功能,例如 cell.textLabel.text,您需要这样做:

cell.textLabel.text = [object objectForKey:@"name"];
cell.textLabel.backgroundColor = [UIColor clearColor]; 
cell.textLabel.opaque = NO;

希望这对将来的其他人有所帮助。

【问题讨论】:

  • 某处有故事板吗?我在存储库中没有看到。
  • 由于某种原因它被本地化了。它位于 en.lprog 目录中。
  • 知道了。一切都很好,除了您在自定义单元格上使用内置的 textLabel 属性。当您设置它时,单元格将取消隐藏它并且标签的背景颜色为纯白色。当您选择单元格时,它会暂时使背景清晰,您可以看到它后面的项目。如果你想使用内置的 textLabel 没问题,只需将背景颜色设置为清除:cell.textLabel.backgroundColor = [UIColor clearColor]; cell.textLabel.opaque = NO;
  • 我想知道如何在“MovieCell”中显示“Movie 1”的值;请帮助我,因为我最近两天正在搜索。
  • @Jasper 您可以为每个CellIdentifier 自定义单元格,在本例中为MovieCell。您只想创建一个标签之类的东西,并在加载后将文本设置为 Movie1 的名称。

标签: iphone objective-c ios ipad uitableview


【解决方案1】:

在您的- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 方法中,您可以根据indexPath 返回多种类型的单元格。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row > 5) { // Your conditions here to choose between Books and Movies
        BookCell *cell = [tableView dequeueReusableCellWithIdentifier:@"bookCell"];
        if (!cell)
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault     reuseIdentifier:@"bookCell"];
        }
        return cell;
    } else {
        MovieCell *cell = [tableView dequeueReusableCellWithIdentifier:@"movieCell"];
        if (!cell)
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault     reuseIdentifier:@"movieCell"];
        }
        return cell;
    }
return nil;
}

【讨论】:

  • 在带有情节提要的 iOS 5 下,您无需再检查 nil 单元格并实例化。 -dequeueReusableCellWithIdentifier: 会为你解决这个问题。
  • 如果你从 tableView:cellForRowAtIndexPath 返回 nil,你的应用会崩溃。你应该在最后返回一些东西。在您的情况下,您永远无法通过 if/else,所以没关系,但需要注意一些事情。
  • 你可以使用一些类型转换来避免返回nil。至于您的第一条评论,您可以使用故事板,但这并不意味着您不能在代码中实例化 UITableView 或子类 UITableViewController。所以在dequeueReusableCellWithIdentifier 之后检查nil 可能会有用,因为dequeueReusableCellWithIdentifier 仍然可以返回nil
  • 我只是指您最后一个“return nil”语句,在这种情况下实际上是多余的。如果你曾经在那里“返回 nil”,应用程序就会崩溃。
  • 进行额外检查当然没有坏处,但问题特别提到他只关心情节提要支持,因此将这些排除在外也可以。
【解决方案2】:

非常感谢所有提供帮助的人,尤其是 atticus,他完成了最后的工作。

最终的工作是将数据结构更改为字典数组,然后将Key: type Value: book/movie/music 添加到每个条目。数据结构现在看起来像:

Array[0]: Dictionary: [Key: type Value: book], [Key: name Value: Physics];
Array[1]: Dictionary: [Key: type Value: music], [Key: name Value: Rock];

然后配置我这样做的单元格:

NSString *CellIdentifier = @"Cell";
NSDictionary *object = [self.listOfStuff objectAtIndex:indexPath.row];
if ([[object objectForKey:@"type"] isEqualToString:@"book"]){
    CellIdentifier = @"BookCell";
}else if ([[object objectForKey:@"type"] isEqualToString:@"music"]){
    CellIdentifier = @"MusicCell";
}else if ([[object objectForKey:@"type"] isEqualToString:@"movie"]){
    CellIdentifier = @"MovieCell";
}

每一个在故事板中都有一个不同的 tableviewcell。我们发现如果您想使用任何内置单元格功能,例如 cell.textLabel.text,您需要这样做:

cell.textLabel.text = [object objectForKey:@"name"];
cell.textLabel.backgroundColor = [UIColor clearColor]; 
cell.textLabel.opaque = NO;

希望这对将来的其他人有所帮助。

【讨论】:

    【解决方案3】:

    在您的故事板中,将您的 tableView 设置为使用动态原型。然后,为您要使用的每种单元格创建一个单元格。适当地自定义这些,然后在检查器中为每个人提供一个唯一的重用标识符(例如 MovieCell)。

    然后,在您的 tableview:cellForRowAtIndexPath: 方法中,为该索引路径处的内容确定合适的单元格类型。如果 indexPath 处的单元格应该是电影单元格,则可以使用以下命令创建单元格:

    static NSString * MovieCellIdentifier = @"MovieCell"; // This must match the storyboard
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MovieCellIdentifier];
    

    这将为您提供您在情节提要中指定为“MovieCell”的单元格。如果您需要进一步自定义它,请创建一个 UITableViewCell 子类并为 Storyboard 中的单元格指定该子类。然后,您可以通过转换返回的单元格来参考这里的属性等进行自定义:

    MovieTableViewCell *movieCell = (MovieTableViewCell *)cell;
    // customize
    

    【讨论】:

    • 一个问题:在cellForRowAtIndexPath函数的最后,会返回哪个单元格?因为你有很多自定义的 Tableviewcell,例如MovieTableViewCell、BookTableViewCell……最后你将如何返回它们?
    【解决方案4】:

    我的意见是您应该在一个单元中实现所有单元类型。这意味着您应该拥有一个 UITableViewCell 类和所有这些类的 .xib。然后在cellForRowAtIndexPath中,创建单元格,然后根据实际需要,显示/隐藏组成一本书或一部电影的子视图。

    在这样的设计中,您的单元格会有些重量级。但是,它仍然比使用多个单元格类更好,因为这种方式单元格重用效率更高 ([UITableView dequeueReusableCellWithIdentifier])。

    我相信 UITableView 是针对一种类型的单元格设计的。因此,如果您的布局发生变化,您仍然可以将它们放在一个位置并使用框架或显示/隐藏来控制单元格的行为。

    【讨论】:

    • 使用故事板,可以创建多种单元格类型,并使代码更具可读性。
    • 我同意@atticus。我尝试了这种方法,它使滚动有点滞后,因为有很多子视图回收。我最终重新创建了我的课程。在 cellForRowAtIndexPath 处有很多类回收,使表格滚动更加流畅和快速。
    【解决方案5】:

    我认为您应该使用以下作为您的单元格标识符。

    - (UITableViewCell *)tableView:(UITableView *)tmpTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    NSString *cellIdentifier            =   [NSString stringWithFormat:@"Cell%d%d",indexPath.section,indexPath.row];
    UITableViewCell *cell               =   [tmpTableView dequeueReusableCellWithIdentifier:cellIdentifier]; 
    if (nil == cell) {
        cell    =   [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    
    // do ur stuff here
    
    }
    return cell;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-21
      相关资源
      最近更新 更多