【问题标题】:iOS 14 PickerView cutting off textiOS 14 PickerView 截断文本
【发布时间】:2026-01-07 14:25:03
【问题描述】:

我有一个在 iOS 14 上无法正确显示文本的pickerview。有人知道如何解决这个问题吗?好像有一个子视图覆盖了文本?

是因为我使用的是自定义标签吗?

func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
        let pickerLabel = UILabel()
        let titleData = pickerDataSource[row]
        
        pickerView.subviews[1].backgroundColor = .clear
        pickerView.subviews[0].backgroundColor = .clear
        
        let myTitle = NSAttributedString(string: titleData, attributes: [NSAttributedString.Key.font:UIFont.systemFont(ofSize: 18),NSAttributedString.Key.foregroundColor:UIColor.black])
        pickerLabel.attributedText = myTitle
        return pickerLabel
    }

【问题讨论】:

  • 发布您的代码。
  • 刚刚更新:)
  • 使用 View Debugger 查看是否有东西覆盖了文本。
  • 我正在经历完全相同的事情,只是使用了更简单的自定义标签。没有任何东西覆盖文本;您经常可以看到新的矩形区域包含第一个字符的几个像素。到目前为止,我发现的唯一解决方案是使用中心对齐。向 Apple 提交错误报告:feedbackassistant.apple.com

标签: ios swift uipickerview


【解决方案1】:

只需在标签上添加 margin-left 就可以了。

After the fix

原始代码:

extension UILabel {
    func setMargins(margin: CGFloat = 10, _ leftMarginOnly: Bool = true) {
            if let textString = self.text {
                let paragraphStyle = NSMutableParagraphStyle()
                paragraphStyle.firstLineHeadIndent = margin
                paragraphStyle.headIndent = margin
                if !leftMarginOnly {
                    paragraphStyle.tailIndent = -margin
                }
                let attributedString = NSMutableAttributedString(string: textString)
                attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length))
                attributedText = attributedString
            }
        }
}

【讨论】:

  • 方法名称应明确说明这是一个错误修复:fixBugMargins。几周后,当您阅读使用此扩展的代码时,您会问自己这是 UIKit 方法还是自定义方法。其次,此方法将适用于所有 UILabel,但该错误存在于 UIDatePicker 中的 UILabel 上。两种可能:将方法移到 UIPickerView 或自定义类 UIKitBugFixes
【解决方案2】:

您可以按照 Nguyen 的建议在 ViewForRow 方法中设置属性字符串,并像这样编辑您的代码

 func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
    let pickerLabel = UILabel()
    let titleData = pickerDataSource[row]
    
    pickerView.subviews[1].backgroundColor = .clear
    pickerView.subviews[0].backgroundColor = .clear
    
    let myTitle = NSAttributedString(string: titleData, attributes: [NSAttributedString.Key.font:UIFont.systemFont(ofSize: 18),NSAttributedString.Key.foregroundColor:UIColor.black])
    
    let margin : CGFloat = 12.0
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.firstLineHeadIndent = margin
    paragraphStyle.headIndent = margin
    myTitle.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: myTitle.length))
    
    pickerLabel.attributedText = myTitle
    return pickerLabel
}

【讨论】:

    【解决方案3】:

    我正在使用更简单的标签生成方法;目前我的解决方法是使用居中对齐,如下例所示。

    func pickerView(_ pickerView: UIPickerView,
                    viewForRow row: Int,
                    forComponent component: Int,
                    reusing view: UIView?) -> UIView
    {
        let pickerLabel = UILabel()
        pickerLabel.text = "Test string"
        pickerLabel.font = UIFont(name: "Ropa Sans", size: 18)
        pickerLabel.textColor = UIColor.white
        pickerLabel.textAlignment = NSTextAlignment.center
    }
    

    我想知道这是否是与字体相关的缺陷,但由于您使用的是系统字体,我得出结论可能不是。

    【讨论】:

      【解决方案4】:

      一种破解方法是将下面的代码添加到pickerView(viewForRow:)

      pickerView.subviews[0].subviews.first?.subviews.last?.clipsToBounds = false
      

      pickerView.subviews[0].subviews.first?.subviews包含3个view,最后一个是包裹你view的真正的view,它的宽度比picker view要小,所以会修剪真实的内容。

      【讨论】: