枚举可变属性字符串(下划线按钮)

Enumerate over a Mutable Attributed String (Underline Button)

我正在尝试创建一个 UIButton 允许对所选文本加下划线。这是我当前的代码:

func underline() {
if let textRange = selectedRange {
    let attributedString = NSMutableAttributedString(attributedString: textView.attributedText)
    textView.textStorage.addAttributes([.underlineStyle : NSUnderlineStyle.single.rawValue], range: textRange)
    }
}

它目前正在加下划线,但我遇到的问题是我需要检查当前文本是否已经加下划线以及是否删除了下划线。我似乎无法用 NSMutableAttributedString.

解决这个问题

我用斜体 UIButton 这样做:

func italic() {
    if let textRange = selectedRange {
        let attributedString = NSAttributedString(attributedString: textView.attributedText)
        attributedString.enumerateAttribute(.font, in: textRange, options: []) { (font, range, pointee) in
            let newFont: UIFont
            if let font = font as? UIFont {
                let fontTraits = font.fontDescriptor.symbolicTraits
                if fontTraits.contains(.traitItalic) {
                    newFont = UIFont.systemFont(ofSize: font.pointSize, weight: .regular)
                } else {
                    newFont = UIFont.systemFont(ofSize: font.pointSize).italic()
                }
                textView.textStorage.addAttributes([.font : newFont], range: textRange)
            }
        }
    }
}

第一个函数如何实现检查当前文本是否有下划线属性?

我们目前的代码:

func isUnderlined(attrText: NSAttributedString) -> Bool {
    var contains: ObjCBool = false
    attrText.enumerateAttributes(in: NSRange(location: 0, length: attrText.length), options: []) { (dict, range, value) in
        if dict.keys.contains(.underlineStyle) {
            contains = true
        }
    }
    return contains.boolValue
}

func underline() {
    if let textRange = selectedRange {
        let attributedString = NSMutableAttributedString(attributedString: textView.attributedText)
        switch self.isUnderlined(attrText: attributedString) {
        case true:
            print("true")
            textView.textStorage.removeAttribute(.underlineStyle, range: textRange)
        case false:
            print("remove")
            textView.textStorage.addAttributes([.underlineStyle : NSUnderlineStyle.single.rawValue], range: textRange)
        }
    }
}

要检查文本是否已加下划线,您可以简单地 运行 contains(_:) 文本的属性,即

func isUnderlined(attrText: NSAttributedString) -> Bool {
    var contains: ObjCBool = false
    attrText.enumerateAttributes(in: NSRange(location: 0, length: attrText.length), options: []) { (dict, range, value) in
        if dict.keys.contains(.underlineStyle) {
            contains = true
        }
    }
    return contains.boolValue
}

示例:

let attrText1 = NSAttributedString(string: "This is an underlined text.", attributes: [.underlineStyle : NSUnderlineStyle.styleSingle.rawValue])
let attrText2 = NSAttributedString(string: "This is an underlined text.", attributes: [.font : UIFont.systemFontSize])

print(self.isUnderlined(attrText: attrText1)) //true
print(self.isUnderlined(attrText: attrText2)) //false

您可以根据需要在 UITextView 中使用上述逻辑。

要删除属性,

1. 首先必须是NSMutableAttributedString.

2. 然后要删除属性,请对属性字符串使用 removeAttribute(_:range:) 方法。

let attrText1 = NSMutableAttributedString(string: "This is an underlined text.", attributes: [.underlineStyle : NSUnderlineStyle.styleSingle.rawValue])

print(self.isUnderlined(attrText: attrText1)) //true
if self.isUnderlined(attrText: attrText1) {
    attrText1.removeAttribute(.underlineStyle, range: NSRange(location: 0, length: attrText1.string.count))
}
print(self.isUnderlined(attrText: attrText1)) //false

点击按钮时处理 textView

@IBAction func onTapButton(_ sender: UIButton) {
    if let selectedTextRange = self.textView.selectedTextRange {
        let location = self.textView.offset(from: textView.beginningOfDocument, to: selectedTextRange.start)
        let length = self.textView.offset(from: selectedTextRange.start, to: selectedTextRange.end)
        let range = NSRange(location: location, length: length)

        self.textView.attributedText.enumerateAttributes(in: range, options: []) { (dict, range, value) in
            if dict.keys.contains(.underlineStyle) {
                self.textView.textStorage.removeAttribute(.underlineStyle, range: range)
            } else {
                self.textView.textStorage.addAttributes([.underlineStyle : NSUnderlineStyle.styleSingle.rawValue], range: range)
            }
        }
    }
}