多个自定义 UITableViewCell 相互覆盖 Swift

Posted

技术标签:

【中文标题】多个自定义 UITableViewCell 相互覆盖 Swift【英文标题】:Multiple Custom UITableViewCell Overwriting Eachother Swift 【发布时间】:2016-01-06 22:48:45 【问题描述】:

我正在尝试创建一个包含多个自定义 UITableViewCells 的表格视图。如果我只使用一个自定义单元格,则会显示正确的单元格。如果我添加第二个单元格,则显示第二个单元格会覆盖第一个单元格并禁止交互,第二个单元格会显示第一个自定义单元格的默认数据,直到它被选中,然后才会显示正确的单元格。

class ViewController: UIViewController 

@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    let nib1 = UINib(nibName: "AccountCell1", bundle: nil)
    tableView.registerNib(nib1, forCellReuseIdentifier: "SettingCell1")
    let nib2 = UINib(nibName: "AccountCell2", bundle: nil)
    tableView.registerNib(nib2, forCellReuseIdentifier: "SettingCell2")
    //removing empty rows
    tableView.tableFooterView = UIView()


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


 func numberOfSectionsInTableView(tableView: UITableView) -> Int 

    return 1


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

    return 2



 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    /*let cell = tableView.dequeueReusableCellWithIdentifier( "AccountCell", forIndexPath: indexPath) as! UITableViewCell*/
    let cell1 = tableView.dequeueReusableCellWithIdentifier( "SettingCell1", forIndexPath: indexPath) as! AccountCell1Controller
    let cell2 = tableView.dequeueReusableCellWithIdentifier( "SettingCell2", forIndexPath: indexPath) as! AccountCell2Controller

    // Configure the cell...
    if(indexPath.row == 0)
    
        let imageName = "Amanda.jpeg"
        let image = UIImage(named: imageName)
        cell1.UserImage.image = image
        cell1.UserLabel.text = "@AmandaSmith"
        cell1.setNeedsLayout()
        return cell1
    
    else
    
        return cell2
    



 func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
    if(section == 0)
    
        return "John Smith"
    
    else if(section == 1)
    
        return "Settings"
    
    else if(section == 2)
    
        return "About"
    
    return ""

 func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
    if(indexPath.row == 0)
    
        return 204
    
    else if(indexPath.row == 1)
    

        return 61
    
    else 

        return 44
    




My Account 单元控制器,2 是两个按钮,对应的动作

 class AccountCell1Controller: UITableViewCell 
@IBOutlet weak var UserImage: UIImageView!
@IBOutlet weak var UserLabel: UILabel!

override func awakeFromNib() 
    super.awakeFromNib()
    let user = UserData.self
    // Initialization code


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

    // Configure the view for the selected state




【问题讨论】:

请提供您的cellForRowAtIndexPath 方法的代码示例,以及您与单元格交互的任何其他地方。如果不查看一些代码,我们将无法帮助您诊断问题。 @AlexPopov 我编辑了我的问题,很抱歉我在添加代码之前不小心点击了提交问题。 【参考方案1】:

问题是即使您没有为该行创建单元格,您也正在使cell1 出队。

尝试仅将给定indexPath.row 实际需要的单元格出列:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
  // Configure the cell...

  if(indexPath.row == 0) 
    let cell1 = tableView.dequeueReusableCellWithIdentifier( "SettingCell1", forIndexPath: indexPath) as! AccountCell1Controller
    let imageName = "Amanda.jpeg"
    let image = UIImage(named: imageName)
    cell1.UserImage.image = image
    cell1.UserLabel.text = "@AmandaSmith"
    cell1.setNeedsLayout()
    return cell1
   else 
    let cell2 = tableView.dequeueReusableCellWithIdentifier( "SettingCell2", forIndexPath: indexPath) as! AccountCell2Controller
    return cell2
  



要了解为什么出队会破坏事情,了解 TableView 的工作原理很重要。

假设您的表格中有 100 个单元格。如果您的设备(例如 iPhone)一次只能显示 10 个,那么创建和管理所有 100 个单元将是浪费的。出队基于此原则工作,您只需要分配尽可能多的单元格,就像您将要显示的那样。所以每次你需要一个新的单元格时(每次调用cellForRowAtIndexPath)你只想出列你需要的单元格类型,如果一个单元格同时离开屏幕,你可以重复使用它,而不是删除它并经历(可能)繁重的创建新单元的过程。

知道了这一点,我仍然有点模糊为什么将两个单元格出列以获取单个索引会破坏布局,但它显然混淆了 TableView。作为在单个 tableView 中处理多个自定义单元格时的一般经验法则,最好将 cellForRowAtIndexPath 拆分为每种类型的单元格的单独函数(如果有意义的话,也可能用于不同的部分)。这样,您可以在indexPath.rowswitch 并根据行调用您自己的自定义dequeueThisSettingsCelldequeueOtherSettingsCell,将单元格返回到cellForRowAtIndexPath,然后将其返回到tableView。这也大大缩短了cellForRowAtIndexPath,明确了哪些单元格在哪些行/节中出列,并将每个单元格的设置分成不同的功能(这有助于提高清晰度和可读性)。

【讨论】:

啊啊啊啊!太好了谢谢! @AlexPopov 好的,我将尝试解释并编辑答案,但在这里快速指针:cellForRowAtIndexPath 为您的 TableView 中的每个 IndexPath 调用。首先,将不需要的单元格出列是浪费的(例如,每次通过都将 cell1cell2 出列)但它也会混淆 TableView 并且不确定如何处理 cell1,因为它为 IndexPath2 出队。在这种情况下,为每种单元格类型创建单独的出队函数并仅调用其中一个会很有帮助。它还使代码更整洁:)

以上是关于多个自定义 UITableViewCell 相互覆盖 Swift的主要内容,如果未能解决你的问题,请参考以下文章

将多个自定义 UITableViewCell 链接到单个 xib

自定义 UITableViewCell 不会在 setNeedsDisplay 上重绘

在 Swift 中将自定义 UITableViewCell 共享到多个 UITableViewController

可折叠部分和每个部分的多个自定义 UITableViewCell

自定义 UITableViewCell 中的 UIButton 导致在多个单元格中选择按钮

使用 xib 和自动布局的自定义 UITableViewCell 无法在顶部的多个单元格中正确显示