Show two different custom cells in same uitableview - swift firebase

前端 未结 6 1552
心在旅途
心在旅途 2021-02-06 20:15

I am currently having a problem with displaying two different types of custom cells on the same uitableview.

What I have managed so far, is receiving the \"updates\" to

相关标签:
6条回答
  • 2021-02-06 20:19

    I am not sure what you want to achieve. If you want to display the number of cells updates[] and updatesTask[] have elements you can do it like this

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

    then you can modify your cellForRowAtIndexPath method like this:

    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
    }
    

    with the if condition you can choose from which array you are taking data. But be careful to name an array exactly the same as another constant like you did here

    let updateTask = updatesTask[indexPath.row]
    
    0 讨论(0)
  • 2021-02-06 20:19

    You can create a simple View Model, that will hold the multiple item types:

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

    Then create a model item type for each section. For example:

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

    Once you configure all your section items with, you can save them in ViewModel:

    class ProfileViewModel {
       var items = [ViewModelItem]()
    }
    

    And add to you TableViewController:

    let viewModel = ViewModel()
    

    In this case, NumberOfSections, NumberOfRows and CellForRowAt methods will be clean and simple:

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

    Configuring the section title will also be very neat:

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

    Please check my recent tutorial on this topic, that will answer your question with the details and examples:

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

    0 讨论(0)
  • 2021-02-06 20:24
        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()
            }
        }
    
    0 讨论(0)
  • 2021-02-06 20:25

    @Callam's answer is great if you want to put them in two sections.

    This is the solution if you want all to be in one section.

    First, in numberOfRowsInSection method you need to return the sum of those two array counts like this: return (updates.count + updatesTask.count)

    Then you need to configure cellForRowAtIndexPath method like this:

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

    This will display all cells followed by all cellTasks.


    If updates array and updatesTask array have equal number of items and you want to display them one by one you can use this:

    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
        }
    
    }
    
    0 讨论(0)
  • 2021-02-06 20:34

    For each row you have to choose if you want to display one type of cell or the other but not both. You should have a flag in numberOfRowsInSection telling your method that you want to load Cell or CellTask and then return the correct number of rows.

    0 讨论(0)
  • 2021-02-06 20:38

    You should return total number of rows in your numberOfRowsInSection method. so you can return summation of your both array's count something like,

     return updates.count + updatesTask.count
    

    now in your cellForRowAtIndexPath method you can differentiate your cell something like,

        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
        }
    
    0 讨论(0)
提交回复
热议问题