如何在单个 tableView 中创建各种类型的单元格?

Posted

技术标签:

【中文标题】如何在单个 tableView 中创建各种类型的单元格?【英文标题】:How to create a various type of cells in a single tableView? 【发布时间】:2017-12-17 13:00:33 【问题描述】:

我目前正在开发一个应用程序,它具有一半 Uber、一半 Tinder 等功能。

我想创建一个用于编辑配置文件的 TableView,使其看起来像 Tinder 的配置文件编辑视图。

我成功地制作了第一个单元格用于拾取个人资料图像和第二个单元格用于 textLabel。

我想制作第三个单元格,它有一个可编辑的 TextView(不是 textField,因此用户可以输入几行单词)但是代码没有按我的预期工作。

虽然我在自定义单元格类中创建了一个 textView 并将其设置为我的 tableViewController 类中的第三个 tableView 单元格,但它似乎没有出现在我的模拟器上。

我仍然不太确定为单个 tableView 制作多种类型的单元格的好方法是什么,所以如果有其他更好的方法,我很想知道。

我与此问题相关的代码如下。

视图控制器

//EditProfileViewController For The Profile Edit view
class EditProfileViewController: UINavigationController 

override func viewDidLoad() 
    super.viewDidLoad()

    // Do any additional setup after loading the view.


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.



表视图控制器

//MyTableViewController for the EditProfileViewController
class EditProfileTableViewController: UITableViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITextViewDelegate 
override func viewDidLoad() 
    super.viewDidLoad()



    override func numberOfSections(in tableView: UITableView) -> Int 

    return 3


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    if section == 0 
        return 5
     else if section == 1 
        return 2
     else 
        return 4
    



override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    //link my custom Cell here
    if let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCell", for: indexPath) as?  MyCellTableViewCell 

        if indexPath.section == 0 

            if indexPath.row  == 0 
                //this row is for an Image Picker
                cell.textLabel?.text = "edit profile image"
             else if indexPath.row == 1 
                //this row is just like a title of third cell which is editable self description
                cell.textLabel?.text = "Describe yourself"
                cell.isUserInteractionEnabled = false
             else if indexPath.row == 2 
                //this row is an editable self description
                cell.addSubview(cell.selfDescritionTextView)
                cell.selfDescritionTextView.delegate = self
                cell.selfDescritionTextView.isEditable = true
                cell.selfDescritionTextView.text = "Enter some descriptions here"


            

        

        else if indexPath.section == 1 
            cell.textLabel?.text = "section 1"


        

        else if indexPath.section == 2 
            cell.textLabel?.text = "section 2"

        


        return cell
     else 
        //Just in case
        return UITableViewCell()
    



TableViewCell

//MyCellTableViewCell
class MyCellTableViewCell: UITableViewCell 

//create a textView for self description
var selfDescritionTextView = UITextView()

//init
override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: .default, reuseIdentifier: "MyCustomCell")
    selfDescritionTextView = UITextView(frame: self.frame)
    self.addSubview(selfDescritionTextView)


required init?(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)



override func awakeFromNib() 
    super.awakeFromNib()
    // Initialization code


override func setSelected(_ selected: Bool, animated: Bool) 
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state



如果您需要了解比我在这里展示的更多的代码,请告诉我。

我并不沉迷于这种创建我的编辑配置文件视图的方法,所以如果有人知道比这更好的其他方法,我也很想知道。

谢谢

【问题讨论】:

所有单元格是否都嵌入在表格视图中?所有单元格都有自定义类吗? 你可以使用断点并检查控件是否通过 cellForRow if condition : if let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCell", for: indexPath) as? MyCellTableViewCell 您是在情节提要中使用 tableview 原型单元格还是为 MyCellTableViewCell 使用自定义单元格 xib? >Ahmad F 因为我不知道我可以在主情节提要中制作多个单元格,所以我只制作了一个单元格并为其提供了自定义类。在 tableView 控制器类中,我为每个部分和行定义了内容,因此从技术上讲,所有单元格都嵌入在表格视图中,并且在我的理解中具有相同的自定义类。这有意义吗? >MBN 我通过将 print 放到 if 语句内部的控制台来检查控制是否进入了 cellForRow if 条件,它起作用了!我在情节提要中创建了一个原型单元格,并为该单元格制作了一个 TableViewCell 文件,并在文件中设置了重用标识符以链接它们。 【参考方案1】:
override func viewDidLoad() 
   super.viewDidLoad()

   // Do any additional setup after loading the view.
   tableView.register(UINib(nibName: TableViewCell1.NibName, bundle: nil), forCellReuseIdentifier: TableViewCell1.Identifier)
   tableView.register(UINib(nibName: TableViewCell2.NibName, bundle: nil), forCellReuseIdentifier: TableViewCell2.Identifier)
   tableView.register(UINib(nibName: TableViewCell3.NibName, bundle: nil), forCellReuseIdentifier: TableViewCell3.Identifier)

您将分别拥有 3 个自定义表格视图单元格及其子视图:

class MyCellTableViewCell1: UITableViewCell 
   static var NibName: String = String(describing: TableViewCell1.self)
   static var Identifier: String = "TableViewCell1"

   func configure()  ... 

然后:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
   let cell: UITableViewCell
   // link my custom Cell here. 

   if indexPath.row  == 0, let dequeuedCell = tableView.dequeueReusableCell(withIdentifier: TableViewCell1.Identifier, for: indexPath) as? TableViewCell1 
      dequeuedCell.configure()
      cell = dequeuedCell
   
   else if indexPath.row  == 1, let dequeuedCell = tableView.dequeueReusableCell(withIdentifier: TableViewCell2.Identifier, for: indexPath) as? TableViewCell2 
      dequeuedCell.configure()
      cell = dequeuedCell
   
   else if indexPath.row  == 2, let dequeuedCell = tableView.dequeueReusableCell(withIdentifier: TableViewCell3.Identifier, for: indexPath) as? TableViewCell3 
      dequeuedCell.configure()
      cell = dequeuedCell
   
   else 
      cell = UITableViewCell()
   


   return cell


【讨论】:

感谢您的回答!从这里的所有 cmets 来看,似乎我需要在情节提要中制作 3 个单元格,并为每个单元格提供重用标识符!然后分别制作自定义单元格。老实说,我不知道我可以在情节提要中创建多个单元格(所以我一直在努力用一个原型单元格制作多个单元格......)!我会试试看!再次感谢你!【参考方案2】:

像这样注册多个 nib 文件,但它在 viewDidLoad

  tableView.register(UINib(nibName: "TableViewCell1", bundle: nil), forCellReuseIdentifier: CellIdentifier1)

  tableView.register(UINib(nibName: "TableViewCell2", bundle: nil), forCellReuseIdentifier: CellIdentifier2)

  tableView.register(UINib(nibName: "TableViewCell3", bundle: nil), forCellReuseIdentifier: CellIdentifier3)

【讨论】:

我在 tableViewController 类 (viewDidLoad) 中注册了我的 cellClass,并且 textView 确实出现了!!但它出现在第一个单元格上,该单元格曾经是一个图像选择器。我猜是因为我在自定义单元格文件中定义了 textView 但在我的 tableViewController 中定义了一个图像选择器(第一行单元格)?我只使用了一个具有重用标识符的原型单元,因此它也可能导致它......

以上是关于如何在单个 tableView 中创建各种类型的单元格?的主要内容,如果未能解决你的问题,请参考以下文章

我需要在 TableView 中创建基于图像的自定义附件类型的示例代码

如何在tableView swift的Xib Cell中创建内部视图动态

如何在 swift 中在动态 TableView 中创建动态 tableView?

如何在 iOS 中创建具有动态 tableview 高度的动态 tableview 单元格

如何从单个数据框中创建具有不同内容的多个 PDF?

如何在 django 中创建表单和模型中使用的字段的单选按钮