在同一个 uitableview 中显示两个不同的自定义单元格 - swift firebase

Posted

技术标签:

【中文标题】在同一个 uitableview 中显示两个不同的自定义单元格 - swift firebase【英文标题】:Show two different custom cells in same uitableview - swift firebase 【发布时间】:2016-09-19 11:12:17 【问题描述】:

我目前在同一个 uitableview 上显示两种不同类型的自定义单元格时遇到问题。

到目前为止,我所管理的是接收更新单元的“更新”,称为cell。我只是不知道如何让 numberOfRowsInSection 返回两个值,所以我的两个单元格都会显示。

让我通过我的代码来解释一下:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int 
        return 1
    

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return updates.count
        return updatesTask.count // I CANNOT DO THIS - what can I do instead?
    



    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
        let cell:updateTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! updateTableViewCell
        let cellTask:tasksTableViewCell = tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as! tasksTableViewCell


        let update = updates[indexPath.row]
        let updateTask = updatesTask[indexPath.row]


        // Example of the two different cells that need different data from firebase
        cell.nameLabel.text = update.addedByUser
        cellTask.nameLabel.text = updateTask.addedByUser

您可能会看到,let updateTask 正在尝试获取indexPath.row,但这是不可能的,因为我不能在numberOfRowsInSection 中有两个返回值,这是一个问题,因为该数字指的是数据存储在我的 firebase 数据库中的位置。如何修改它以使其正常工作?

希望你们明白我的意思,否则请告诉我,我会尽力解释得更好:-)

【问题讨论】:

请添加 cellForRowAtIndexPath 方法的其余部分,因为这在这种情况下也很重要。 请告诉我您希望以什么顺序显示两个不同的单元格?所有单元格后跟所有任务单元格? @SamM 这就是我目前所有的cellForRowAtIndexPath,如果我让它工作,以后还会有更多,我想在 cellTask​​ 之前显示单元格 - 如果可能的话? 检查我的答案,它将显示所有单元格,然后显示所有单元格任务。如果您需要它们像 cell/cellTask​​/cell/cellTask​​... 告诉我,我会更新答案。 我宁愿拥有那个!那将是真棒! @萨姆 【参考方案1】:

如果您想将它们分成两个部分,@Callam 的回答非常棒。

如果您希望所有人都在一个部分中,这就是解决方案。

首先,在numberOfRowsInSection 方法中,您需要返回这两个数组计数的总和,如下所示:return (updates.count + updatesTask.count)

那么你需要像这样配置cellForRowAtIndexPath方法:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    if indexPath.row < updates.count
        // Updates
        let cell:updateTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! updateTableViewCell
        let update = updates[indexPath.row]
        cell.nameLabel.text = update.addedByUser
        return cell
     else 
        // UpdatesTask
        let cellTask:tasksTableViewCell = tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as! tasksTableViewCell
        let updateTask = updatesTask[indexPath.row-updates.count]
        cellTask.nameLabel.text = updateTask.addedByUser
        return cellTask
    


这将显示所有单元格,然后显示所有单元格任务。


如果updates 数组和updatesTask 数组有相同数量的项目,并且你想一个一个地显示它们,你可以使用这个:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    if indexPath.row % 2 == 0 
        // Updates
        let cell:updateTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! updateTableViewCell
        let update = updates[indexPath.row/2]
        cell.nameLabel.text = update.addedByUser
        return cell
     else 
        // UpdatesTask
        let cellTask:tasksTableViewCell = tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as! tasksTableViewCell
        let updateTask = updatesTask[indexPath.row/2]
        cellTask.nameLabel.text = updateTask.addedByUser
        return cellTask
    


【讨论】:

有什么方法可以混合细胞吗?随机显示它们,而不是先显示所有更新,然后再显示所有 updateTasks? @D.Finna updates 数组和updatesTask 数组是否有相同数量的项目? 哦!我误解了你所说的相同数量的项目是什么意思!不,您不能确定 updates 和 updatesTask 中的项目数是否相等【参考方案2】:
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int 

        return 2
    

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

        switch section 
        case 0:
            return updates.count
        case 1:
            return updatesTask.count
        default:
            return 0
        
        

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

        switch indexPath.section 
        case 0:
            let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! updateTableViewCell
            let update = updates[indexPath.row]

            cell.nameLabel.text = update.addedByUser

            return cell
        case 1:
            let cell = tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as! tasksTableViewCell
            let updateTask = updatesTask[indexPath.row]

            cell.nameLabel.text = updateTask.addedByUser

            return cell
        default:
            return UITableViewCell()
        
    

【讨论】:

【参考方案3】:

对于每一行,您必须选择是显示一种类型的单元格还是显示另一种类型的单元格,但不能同时显示两者。您应该在 numberOfRowsInSection 中有一个标志,告诉您的方法您要加载 Cell 或 CellTask​​,然后返回正确的行数。

【讨论】:

【参考方案4】:

您应该在您的numberOfRowsInSection 方法中返回total number of rows。这样您就可以返回两个数组计数的summation,例如,

 return updates.count + updatesTask.count

现在在您的 cellForRowAtIndexPath 方法中,您可以区分您的细胞,例如,

    let cell:updateTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! updateTableViewCell
    let cellTask:tasksTableViewCell = tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as! tasksTableViewCell



    if indexPath.row % 2 == 1 

        //your second cell - configure and return
        return cellTask
    
    else
    

    //your first cell - configured and return
        return cell
    

【讨论】:

【参考方案5】:

我不确定你想要实现什么。如果你想显示单元格的数量 updates[] 和 updatesTask[] 有元素,你可以这样做

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return (updates.count + updatesTask.count)

然后你可以像这样修改你的 cellForRowAtIndexPath 方法:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    let cell:updateTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! updateTableViewCell
    let cellTask:tasksTableViewCell = tableView.dequeueReusableCellWithIdentifier("TaskCell", forIndexPath: indexPath) as! tasksTableViewCell

if indexPath.row < updates.count
 //update 
 let update = updates[indexPath.row]
 cell.nameLabel.text = update.addedByUser
else
    let updateTask = updatesTask[indexPath.row]
    cellTask.nameLabel.text = updateTask.addedByUser 


    return cell

使用 if 条件,您可以选择从哪个数组中获取数据。 但请注意将数组命名为与您在此处所做的另一个常量完全相同的名称

let updateTask = updatesTask[indexPath.row]

【讨论】:

我会试试你的代码,因为我相信它真的会帮助我解决我的问题。但请告诉我,&gt; 不应该反过来吗?喜欢这个&lt;?如果不是,请告诉我原因,因为我相信反过来说才有意义:-) 应用程序崩溃,因为它在展开可选值时意外发现 nil。错误在这里:if indexPath.row &gt; updates.count 并且 indexPath.row 和 updates.count 都在打印 0 你刚刚发布了这个 sn-p。如果你想要一个完整的答案,你必须发布你的整个班级。您可能没有在课堂上初始化您要求的数组。 奇怪的是,如果我在我的代码中完全摆脱了 cellTask​​,我可以用一个自定义单元格显示我的提要吗?这对我没有意义。 也许你应该先阅读苹果的 UITableView 文档,以便更好地了解它是如何工作的developer.apple.com/reference/uikit/uitableview【参考方案6】:

您可以创建一个简单的视图模型,它将包含多种项目类型:

enum ViewModelItemType 
   case nameAndPicture
   case about
   case email
   case friend
   case attribute


protocol ViewModelItem 
   var type: ViewModelItemType  get 
   var rowCount: Int  get 
   var sectionTitle: String   get 

然后为每个部分创建一个模型项类型。例如:

class ViewModelNameAndPictureItem: ViewModelItem 
   var type: ProfileViewModelItemType 
      return .nameAndPicture
   

   var sectionTitle: String 
      return “Main Info”
   

   var rowCount: Int 
      return 1
   

   var pictureUrl: String
   var userName: String

   init(pictureUrl: String, userName: String) 
      self.pictureUrl = pictureUrl
      self.userName = userName
   

一旦你配置了所有的部分项目,你就可以将它们保存在 ViewModel 中:

class ProfileViewModel 
   var items = [ViewModelItem]()

并添加到您的 TableViewController:

let viewModel = ViewModel()

在这种情况下,NumberOfSections、NumberOfRows 和 CellForRowAt 方法将简洁明了:

override func numberOfSections(in tableView: UITableView) -> Int 
      return viewModel.items.count


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
      return viewModel.items[section].rowCount


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let item = viewModel.items[indexPath.section]
    switch item.type 
          // configure celll for each type
    

配置章节标题也会很整洁:

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
   return viewModel.items[section].sectionTitle

请查看我最近关于此主题的教程,它将通过详细信息和示例回答您的问题:

https://medium.com/ios-os-x-development/ios-how-to-build-a-table-view-with-multiple-cell-types-2df91a206429

【讨论】:

以上是关于在同一个 uitableview 中显示两个不同的自定义单元格 - swift firebase的主要内容,如果未能解决你的问题,请参考以下文章

UITableview 滚动时有两个不同的自定义单元格重叠

使用代码在拆分视图控制器中显示 UITableView

UITableView 中的突出显示按钮反应缓慢

在同一个 UITableView 的不同部分显示多个 NSFetchedResultsController

分层 UITableview

同一个视图中的两个 UITableView