【问题标题】:Enumerate over a Mutable Attributed String (Underline Button)枚举可变属性字符串(下划线按钮)
【发布时间】:2019-05-14 04:57:28
【问题描述】:

我正在尝试创建一个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)
        }
    }
}

【问题讨论】:

    标签: ios swift uitextview nsattributedstring nsmutableattributedstring


    【解决方案1】:

    要检查文本是否已加下划线,您只需在文本的属性上运行 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)
                }
            }
        }
    }
    

    【讨论】:

    • 好的,我会用这个函数做一个if else。不过,我应该如何删除该属性?
    • 好吧,太棒了,我必须将第一个 func (at: 0,) 更改为 1,否则它永远不会调用 if 语句的真实部分......这是正确的吗?
    • 你在说哪个func?我不明白。
    • 带下划线的那个。
    • 更新了答案。我认为这将解决您的问题。如果你能成功,请接受并投票。
    猜你喜欢
    • 1970-01-01
    • 2015-04-14
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    相关资源
    最近更新 更多