更改属性字符串的文本并在Swift中保留属性

问题描述 投票:3回答:3

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

“%重要%^所有进入休息室的雇员^”的最终输出应为:

重要 所有进入休息室的员工

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

%重要% ^ 休息室的所有员工 ^

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

这是我一直用到破裂的代码:

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
3个回答
2
投票

马丁,

我最终使用了非常相似的东西,但是我决定更改正则表达式以包含^标记。这样,我便可以使用“ 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
}

1
投票

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

想法是添加属性and在一圈中删除定界符。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:常规; font-style:斜体; font-size:14.00pt”;}🇳🇱😆ee{}

0
投票

对我有用!

extension UILabel {
    func updateAttributedText(_ text: String) {
        if let attributedText = attributedText {
            let mutableAttributedText = NSMutableAttributedString(attributedString: attributedText)
            mutableAttributedText.mutableString.setString(text)
            self.attributedText = mutableAttributedText
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.