【问题标题】:Change text of an attributed string and retain attributes in Swift在 Swift 中更改属性字符串的文本并保留属性
【发布时间】:2015-06-18 09:08:37
【问题描述】:

对于数据库程序中的输出,我插入了一些标记以指示粗体或斜体的文本,以及一些替代图像的文本。例如:

“%Important% ^所有员工到休息室^”的最终输出应为:

重要 所有员工到休息室

我编写了代码来查找带有“%”符号和“^”符号的文本,但我现在遇到的问题是文本输出如下:

%Important% ^所有员工到休息室^

我想删除这些 % 和 ^,同时保留字符串的格式。

这是我一直使用的代码,直到它中断:

func processText(inString string: String) -> NSAttributedString {

let pattern = ["(?<=\\^).*?(?=\\^)","(?<=\\%).*?(?=\\%)","\\^", "\\%"]
let italicsRegex = NSRegularExpression(pattern: pattern[0], options: .allZeros, error: nil)
let range = NSMakeRange(0, count(string))
let italicsMatches = italicsRegex?.matchesInString(string, options: .allZeros, range: range) as? [NSTextCheckingResult]

var attributedText = NSMutableAttributedString(string: string)

for match in italicsMatches! {
    attributedText.addAttribute(NSFontAttributeName, value: UIFont(name: "Helvetica-Oblique", size: 14.0)!, range: match.range)
}

let boldRegex = NSRegularExpression(pattern: pattern[1], options: .allZeros, error: nil)
let boldMatches = boldRegex?.matchesInString(string, options: .allZeros, range: range) as? [NSTextCheckingResult]

for match in boldMatches!   {
    attributedText.addAttribute(NSFontAttributeName, value: UIFont(name: "Helvetica-Bold", size: 14.0)!, range: match.range)
}

let removeItalicsMarksRegex = NSRegularExpression(pattern: pattern[2], options: .allZeros, error: nil)
let removeItalicsMarksMatches = removeItalicsMarksRegex?.matchesInString(string, options: .allZeros, range: range) as? [NSTextCheckingResult]

var numberOfLoops = 0
for match in removeItalicsMarksMatches! {

    attributedText.replaceCharactersInRange(match.range, withString: "")

}

return attributedText.copy() as! NSAttributedString
}

这适用于 % 匹配(但仅适用于第一个字符)并立即导致 ^ 字符崩溃。

任何有关解决此问题的帮助或建议将不胜感激。谢谢。

【问题讨论】:

    标签: string swift nsmutablestring string-substitution


    【解决方案1】:

    马丁,

    我最终使用了非常相似的东西,但我决定更改正则表达式以包含 ^ 标记。在这样做的过程中,我可以使用“replaceCharactersInRange”方法剪辑包含的属性子字符串的第一个和最后一个字符。到目前为止,这对我的目的来说效果更好一些,因为它是从属性字符串工作的,所以它不会搞砸或删除它的任何属性。

    我附上了正则表达式和处理斜体的代码部分,以供任何人将来参考(再次感谢!):

    func processText(inString string: String) -> NSAttributedString {
    
    let pattern = ["\\^.*?\\^"] //Presented as an array here because in the full code there are a lot of patterns that are run.
    
    
    
    
    let italicsRegex = NSRegularExpression(pattern: pattern[0], options: .allZeros, error: nil) 
    
    //In addition to building the match for this first regular expression, I also gather build the regular expressions and gather matches for all other matching patterns on the initial string ("string") before I start doing any processing.
    
        let range = NSMakeRange(0, count(string.utf16))
    
    let italicsMatches = italicsRegex?.matchesInString(string, options: .allZeros, range: range) as? [NSTextCheckingResult]
    
    var attributedText = NSMutableAttributedString(string: string)
    
    var charactersRemovedFromString = 0
    
    for match in italicsMatches! {
    
        let newRange = NSMakeRange(match.range.location - charactersRemovedFromString, match.range.length) // Take the updated range for when this loop iterates, otherwise this crashes.
        attributedText.addAttribute(NSFontAttributeName, value: UIFont(name: "Helvetica-Oblique", size: 12.0)!, range: newRange)
    
        let rangeOfFirstCharacter = NSMakeRange(match.range.location - charactersRemovedFromString, 1)
    
        attributedText.replaceCharactersInRange(rangeOfFirstCharacter, withString: "")
    
        charactersRemovedFromString += 2
    
        let rangeOfLastCharacter = NSMakeRange(match.range.location + match.range.length - charactersRemovedFromString, 1)
    
        attributedText.replaceCharactersInRange(rangeOfLastCharacter, withString: "")
        }
    
    return attributedText
    }
    

    【讨论】:

      【解决方案2】:

      这是一个可能的解决方案,本质上是 how to catch multiple instances special indicated **characters** in an NSString and bold them in between? 从 Objective-C 到 Swift。

      这个想法是在一个循环中添加属性删除分隔符。 shift 在删除第一个分隔符后,需要变量来调整匹配范围。

      为简单起见,只显示“^...^”处理。

      func processText(inString string: String) -> NSAttributedString {
      
          let pattern = "(\\^)(.*?)(\\^)"
      
          let regex = NSRegularExpression(pattern: pattern, options: nil, error: nil)!
          var shift = 0 // number of characters removed so far
          let attributedText = NSMutableAttributedString(string: string)
          regex.enumerateMatchesInString(string, options: nil, range: NSMakeRange(0, count(string.utf16))) {
              (result, _, _) -> Void in
              var r1 = result.rangeAtIndex(1) // Location of the leading delimiter
              var r2 = result.rangeAtIndex(2) // Location of the string between the delimiters
              var r3 = result.rangeAtIndex(3) // Location of the trailing delimiter
              // Adjust locations according to the string modifications:
              r1.location -= shift
              r2.location -= shift
              r3.location -= shift
              // Set attribute for string between delimiters:
              attributedText.addAttribute(NSFontAttributeName, value: UIFont(name: "Helvetica-Oblique", size: 14.0)!, range: r2)
              // Remove leading and trailing delimiters:
              attributedText.mutableString.deleteCharactersInRange(r3)
              attributedText.mutableString.deleteCharactersInRange(r1)
              // Update offset:
              shift += r1.length + r3.length
          }
      
          return attributedText.copy() as! NSAttributedString
      }
      

      请注意,enumerateMatchesInString() 采用 NSRange,因此您必须计算 UTF-16 字符数,而不是 Swift 字符数。

      例子:

      let text = "???aaa ^???bbb^ ???eee"
      let attrText = processText(inString: text)
      println(attrText)
      

      输出:

      ???aaa { }???bbb{ NSFont = " font-family: \"Helvetica-Oblique\"; font-weight: normal; font-style: italic; font-size: 14.00pt"; } ???eee{ }

      【讨论】:

      • 感谢您的帮助。我会尽快尝试一下。我确实看到了一些 obj-c 版本,但我只是在学习 Swift,所以 Objective-c 代码翻译不是我自己能做的。
      • 这很奇怪,但一半时间,这段代码返回“执行被中断,原因:EXC_BAD_ACCESS (code=1...)”,一半时间它工作。为什么它会如此不稳定?
      • @DanM:没有。你有输入字符串崩溃的具体例子吗?
      • 是的,当我测试字符串“^我们正在飞行!^ ^我们正在飞行!^”时,它一半时间崩溃,一半时间正确返回字符串。我目前只是在操场上玩它,所以当我使用它时它实际上评估不同: println(processText(inString: "^We are flight!^ ^We are flight!^"))通过删除最后一个括号并将其放回来评估字符串。
      【解决方案3】:

      这对我有用!

      extension UILabel {
          func updateAttributedText(_ text: String) {
              if let attributedText = attributedText {
                  let mutableAttributedText = NSMutableAttributedString(attributedString: attributedText)
                  mutableAttributedText.mutableString.setString(text)
                  self.attributedText = mutableAttributedText
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多