UITableView 可重用的自定义单元格在子视图中显示错误的内容

Posted

技术标签:

【中文标题】UITableView 可重用的自定义单元格在子视图中显示错误的内容【英文标题】:UITableView reusable custom cells show wrong content in subviews 【发布时间】:2015-07-18 13:04:37 【问题描述】:

我有一个 UITableViewController 子类,我在其中使用如下数据填充 UITableView:

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

    let cell = tableView.dequeueReusableCellWithIdentifier("kundeCell") as! KundeCell
    cell.selectionStyle = .None

    let kunde = self.kundenAuszutragen[indexPath.row]

    cell.delegate = self
    cell.kunde = kunde

    cell.allowsSwypeRight = (self.zahlungenImQuartalVonKunde[kunde] == nil) // Abkassieren
    cell.allowsSwypeLeft = self.state == .Austragen                         // Austragen

    cell.abkassierButton.titleAbkassierLabel.showsTextFilled = self.zahlungenImQuartalVonKunde[kunde] != nil

    return cell

这很好用,看起来像这样:

上面的文字是一个UILabel,下面的文字来自一个UIButton(在这两种情况下都是默认的)。右边的€符号是一个自定义UIButton,带有一个自定义UILabel的子视图,显示带有描边效果的€,下面是自定义UIButton的相关代码,在按钮初始化时调用:

private func handleInit()

    // titleAbkassierLabel is the custom UILabel with the stroke
    self.titleAbkassierLabel = AbkassierLabel(frame: CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height))
    self.titleAbkassierLabel.font = UIFont.systemFontOfSize(self.titleAbkassierLabelFontSize)
    self.titleAbkassierLabel.text = self.titleText
    self.titleAbkassierLabel.textColor = UIColor.clearColor()
    self.titleAbkassierLabel.setNeedsDisplay()
    self.addSubview(self.titleAbkassierLabel)

    self.backgroundColor = UIColor.clearColor()

现在,当我设置要填充的单元格的€符号时,它看起来像这样:

然后在 UIButton 子类中调用以下代码:

self.titleAbkassierLabel.showsTextFilled = true

// which then again comes to: (in the titleAbkassierLabel - property)
var showsTextFilled: Bool = true   
    didSet
    
        self.setNeedsDisplay()
    

好吧,这个单元格用填充的€“突出显示”。但是,如果我向下滚动,其他单元格也会突出显示(当然,因为第一个单元格被重复使用,为什么它显示正确的文本(在左侧的标签中)而不是正确的 € 符号?应该的单元格'不被突出,甚至看起来与其他人不同: (与其他单元格比较,€ 似乎更粗)

所以它看起来更厚,但如果我查看 ViewDebugger,我会看到只有一个自定义按钮和一个自定义 € - 标签:

如果您需要更多信息,请发表评论。非常感谢您,我希望您能理解这个问题,尽管有德语属性名称/等等!

编辑:我的单元格代表:

protocol AustragenAbkassierenDelegate

    // Kunde bearbeiten
    func setKundeAusgetragen(kunde: Kunde, animated: Bool) -> Bool
    func setKundeAbkassiert(kunde: Kunde, createZahlung: Bool, endAction: (() -> Void)?) -> UIAlertController?

    func getNextKundeAfterKunde(kunde: Kunde) -> Kunde?

    func showKundeDetailVCWithKunde(kunde: Kunde)

    func showAlertController(alert: UIAlertController!, completionHandler: (() -> Void)?)

但我认为这与问题无关。它只是在发生变化时通知委托(这里是 TableViewController)。

【问题讨论】:

如果你设置showsTextFilled,你会再次调用handleInit吗?如果设置该属性会发生什么? 不,handleInit 只是在我的 UIButton 子类的 initWithCoder 和 initWithFrame 中调用,这是我从情节提要中设置的。可以看到,如果设置了showsTextFilled,标签会在自身上调用setNeedsDisplay来重绘drawTextInRect(rect: CGRect) 中的内容@ 您在 cellforRowAtIndexPath 中设置新文本,但如果欧元符号已填充,则不会。这可能是文本正确但按钮不正确的原因 当你调用 dequeueReusableCellWithIdentifier 时,它要么返回一个全新的单元格,要么重用一个旧单元格。如果它返回一个旧的,它会在返回之前调用该单元格上的 prepareForReuse。 当您设置 showTextFilled 时,您调用的代码可能是问题的一部分。相反,请尝试从头开始重建 titleAbkassierLabel。您可以从 prepareForReuse 调用您的 handleInit,除非您不想继续添加子视图。 【参考方案1】:

尝试在单元格的 prepareForReuse 方法中从头开始重建 titleAbkassierLabel。

【讨论】:

以上是关于UITableView 可重用的自定义单元格在子视图中显示错误的内容的主要内容,如果未能解决你的问题,请参考以下文章

用于 UITableView 的自定义 XIB 单元格在滚动时卡住/卡住

iOS - 使 UITableView 与自定义单元格在按钮单击时可编辑

UITableView 自定义单元格在 iPad Storyboard 上不起作用,但在 iPhone 上起作用

Swift 3 自定义单元格在滚动时更改

uitableview 自定义单元格在向下滚动 uitableview 时丢失其内容

关于单元重用的自定义 UITableViewCell 约束问题