【问题标题】:iOS 10.3: NSStrikethroughStyleAttributeName is not rendered if applied to a sub range of NSMutableAttributedStringiOS 10.3:如果应用于 NSMutableAttributedString 的子范围,则不会呈现 NSStrikethroughStyleAttributeName
【发布时间】:2017-08-21 19:52:13
【问题描述】:

如果应用范围不是整个字符串范围,则不会呈现作为属性添加到NSMutableAttributedString 实例的删除线(单、双...)。

这发生在使用addAttribute(_ name: String, value: Any, range: NSRange)、insert(_ attrString: NSAttributedString, at loc: Int)、append(_ attrString: NSAttributedString)、...

在早期的 iO​​S 10.3 测试版中被 Apple 破坏,在 10.3 最终版中未修复。

信用: https://openradar.appspot.com/31034683

【问题讨论】:

  • 在 iOS 10.3.2 beta 2 中修复
  • 在 10.3.2 当前版本中似乎无法使用,但在 iOS 11 中可以使用。

标签: ios swift uikit


【解决方案1】:

设置基线偏移似乎可以解决它:

[attributedStr addAttribute:NSBaselineOffsetAttributeName value:@0 range:NSMakeRange(0, 10)];
[attributedStr addAttribute:NSStrikethroughStyleAttributeName value:@2 range:NSMakeRange(0, 10)];

这是 iOS 10.3 中已知的bug

【讨论】:

  • 你拯救了这一天! :D
  • 这也适用于上标和下标属性。
  • 它正在工作,但我怀疑“NSBaselineOffsetAttributeName”默认值为零。那为什么我们需要设置值。
  • 这显然是一个错误,所以它一定有某种渲染副作用
【解决方案2】:

将NSBaselineOffsetAttributeName(如here 解释)添加到属性字符串会带回删除线。覆盖 drawText:in: 可能会很慢,尤其是在 Collection View 或 Table View Cells 上。

【讨论】:

    【解决方案3】:

    为我们的特定场景找到了一种解决方法(我们没有使用 UILabel 的属性指定任何样式,但都使用 NSAttributedString 属性):

    /// This UILabel subclass accomodates conditional fix for NSAttributedString rendering broken by Apple in iOS 10.3
    final class PriceLabel: UILabel {
    
        override func drawText(in rect: CGRect) {
            guard let attributedText = attributedText else {
                super.drawText(in: rect)
                return
            }
    
            if #available(iOS 10.3, *) {
                attributedText.draw(in: rect)
            } else {
                super.drawText(in: rect)
            }
        }
    }
    

    注意:如果您将 UILabel 的样式属性与 NSAttributedString 属性混合使用,您应该考虑在渲染之前创建一个新的属性字符串,在其上应用 UILabel 的样式,然后在其上重新应用所有 attributedText 的属性。

    【讨论】:

    • 这让我害了我一整天,很高兴你找到了解决方案
    • 对于它的价值,我还发现对于 iOS 10.3 版本,属性字符串不会使用 UILabel 属性上设置的字体样式呈现​​。因此,例如,如果您使用属性化的 Text 属性,仅指定 UILabel 的字体类型是不够的。您必须通过 NSFontAttributeName 包含所需的字体作为属性
    • 当我按照你所说的覆盖 drawText 函数时,它将忽略我在情节提要中给出的所有标签样式(对齐方式、字体、颜色)。有没有办法将所有这些样式转换为 NSMutableAttributedString 的属性?
    • @Mohammadalijf 我在答案下方的注释中输入的内容 - 从标签的属性中读取它们并重新应用为 NSAttributedString 属性。
    【解决方案4】:

    用 10.3 测试的 swift 3 工作代码

    let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: "₹3500")
    attributeString.addAttribute(NSBaselineOffsetAttributeName, value: 0, range: NSMakeRange(0, attributeString.length))
    attributeString.addAttribute(NSStrikethroughStyleAttributeName, value: 1, range: NSMakeRange(0, attributeString.length))
    productPriceLabel.attributedText = attributeString
    

    【讨论】:

      【解决方案5】:

      斯威夫特 4

      let text = "Hello World"
      let textRange = NSMakeRange(0, text.count)
      let attributedText = NSMutableAttributedString(string: text)
      attributedText.addAttribute(NSAttributedStringKey.strikethroughStyle,
                                  value: NSUnderlineStyle.styleSingle.rawValue,
                                  range: textRange)
      myLabel.attributedText = attributedText
      

      【讨论】:

      • 太棒了!不得不花了将近一个小时来找出那些密钥NSAttributedStringKey.strikethroughStyle等。
      • 重点是使用NSUnderlineStyle.styleSingle.rawValue 而不是NSUnderlineStyle.styleSingle。
      【解决方案6】:

      这是 Xcode 8.3 (8E3004b) / iOS 10.3 已知的错误,使用此解决方法无需额外的代码行,只需在声明 NSMutableAttributedString() 时添加 [NSBaselineOffsetAttributeName:0]

      let attrStr = NSMutableAttributedString(string: YOUR_STRING_HERE, attributes: [NSBaselineOffsetAttributeName : 0])
      
      // Now if you add the strike-through attribute to a range, it will work
      attrStr.addAttributes([
          NSFontAttributeName: UIFont.boldSystemFont(ofSize: 24),
          NSStrikethroughStyleAttributeName: 1
      ], range: NSRange)
      

      【讨论】:

        【解决方案7】:

        对于 Swift 5,NSBaselineOffsetAttributeName 已更改为 kCTBaselineOffsetAttributeName,并且每个新版本都会更改。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-08-21
          • 2016-04-02
          • 1970-01-01
          • 1970-01-01
          • 2016-12-31
          • 1970-01-01
          • 2014-11-15
          • 1970-01-01
          相关资源
          最近更新 更多