使用字符分隔符查找和突出显示 Swift 中的文本

Using character delimiters to find and highlight text in Swift

我之前开发了一个 android 应用程序作为用户的参考指南。它使用 sqlite 数据库来存储信息。数据库存储不带格式的 UTF-8 文本(即粗体或下划线)

为了突出显示哪些文本部分需要格式化,我使用定界符特别是 $$ 将它们括起来,因为这不会作为信息出现在数据库中。在向用户显示文本之前,我编写了一个方法来查找这些定界符并为其中包含的文本添加格式并删除定界符。所以 $$foo$$ 变成了 foo.

我的java代码如下:

private static CharSequence boldUnderlineText(CharSequence text, String token) {
    int tokenLen = token.length();
    int start = text.toString().indexOf(token) + tokenLen;
    int end = text.toString().indexOf(token, start);

    while (start > -1 && end > -1)
    {
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);
        //add the formatting required
        spannableStringBuilder.setSpan(new UnderlineSpan(), start, end, 0);
        spannableStringBuilder.setSpan(new StyleSpan(Typeface.BOLD), start, end, 0);

        // Delete the tokens before and after the span
        spannableStringBuilder.delete(end, end + tokenLen);
        spannableStringBuilder.delete(start - tokenLen, start);
        text = spannableStringBuilder;

        start = text.toString().indexOf(token, end - tokenLen - tokenLen) + tokenLen;
        end = text.toString().indexOf(token, start);
    }

    return text;
}

我已经在 Swift 中为 iOS 重新创建了我的应用程序,除了显示正确的格式外,它是完整的。看来 Swift 对待字符串的方式与其他语言不同。

到目前为止,我已经尝试对我的原始未格式化段落同时使用 NSString 和 String 类型,并设法获得第一个分隔符的范围、开始和结束索引:

func applyFormatting2(noFormatString: NSString, delimiter: String){
    let paragraphLength: Int = noFormatString.length //length of paragraph
    let tokenLength: Int = delimiter.characters.count //length of token

    let rangeOfToken = noFormatString.rangeOfString(formatToken) //range of the first delimiter
    let startOfToken = rangeOfToken.toRange()?.startIndex //start index of first delimiter
    let endOfToken = rangeOfToken.toRange()?.endIndex //end index of first delimiter

    var startOfFormatting = endOfToken //where to start the edit (end index of first delimiter)



}

func applyFormatting(noFormatString: String, token: String){
    let paragraphLength: Int = noFormatString.characters.count
    let tokenLength: Int = token.characters.count   //length of the $$ Token (2)
    let rangeOfToken = noFormatString.rangeOfString(formatToken)    //The range of the first instance of $$ in the no format string
    let startOfToken = rangeOfToken?.startIndex //the starting index of the found range for the found instance of $$
    let endOfToken = rangeOfToken?.endIndex //the starting index of the found range for the found instance of $$


    var startOfFormatting = endOfToken
}

我很欣赏这段代码冗长且包含毫无意义的变量,但它可以帮助我在解决问题时思考我的代码。

我目前正在努力练习如何找到 second/closing 分隔符。我想像在 Java 中那样使用

行从特定索引搜索字符串
int end = text.toString().indexOf(token, start);

但是我不知道如何使用范围来做到这一点。

谁能帮我解决如何正确识别结束分隔符的位置或如何完成代码块以格式化所有必需文本的问题?

谢谢

奥尔多

iOS 方法是使用 NS[Mutable]AttributedStrings。您可以在文本范围内设置属性字典。这些属性包括字体粗细、大小、颜色、行间距等。

使用 NSRegularExpression 怎么样?

public extension NSMutableAttributedString {
    func addAttributes(attrs: [String : AnyObject], delimiter: String) throws {
        let escaped = NSRegularExpression.escapedPatternForString(delimiter)
        let regex = try NSRegularExpression(pattern:"\(escaped)(.*?)\(escaped)", options: [])

        var offset = 0
        regex.enumerateMatchesInString(string, options: [], range: NSRange(location: 0, length: string.characters.count)) { (result, flags, stop) -> Void in
            guard let result = result else {
                return
            }

            let range = NSRange(location: result.range.location + offset, length: result.range.length)
            self.addAttributes(attrs, range: range)
            let replacement = regex.replacementStringForResult(result, inString: self.string, offset: offset, template: "")
            self.replaceCharactersInRange(range, withString: replacement)
            offset -= (2 * delimiter.characters.count)
        }
    }
}

这是你的称呼。

let string = NSMutableAttributedString(string:"Here is some $$bold$$ text that should be $$emphasized$$")
let attributes = [NSFontAttributeName: UIFont.boldSystemFontOfSize(15)]
try! string.addAttributes(attributes, delimiter: "$$")