Swift- 如何删除属性字符串值并使其显示为普通字符串。 (粗体、斜体、下划线、删除线)
Swift- How to remove attributed string values and make it appear as normal string. (Bold, Italic, Underline, Strikethrough)
我想删除属性字符串值并使其显示为普通字符串。 (粗体、斜体、下划线、删除线)
我添加了下面的代码以使其具有属性,但我想知道如何在再次单击该操作时从字符串中删除这些属性。
Bold -
if textBold == true {
let string = text
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.boldSystemFont(ofSize: 25)
]
let attributedString = NSAttributedString(string: string, attributes: attributes)
modifiedString = attributedString
text_View.attributedText = modifiedString
text_View.sizeToFit()
databaseHandlerObj.editLabelData(textProjectId: fetchTextProjectId, text_Id: fetchTextId, text: modifiedString.string)
}
Italic -
if textItalic == true {
text_View.sizeToFit()
let string = text
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.italicSystemFont(ofSize: CGFloat(fontSize))
]
let attributedString = NSAttributedString(string: string, attributes: attributes)
self.modifiedString = attributedString
text_View.attributedText = modifiedString
databaseHandlerObj.editLabelData(textProjectId: fetchTextProjectId, text_Id: fetchTextId, text: modifiedString.string)
}
Underline -
if textUnderline == true {
text_View.sizeToFit()
let string = text
let attributedString = NSMutableAttributedString.init(string: string)
attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: 1, range:
NSRange.init(location: 0, length: attributedString.length))
self.modifiedString = attributedString
text_View.attributedText = modifiedString
databaseHandlerObj.editLabelData(textProjectId: fetchTextProjectId, text_Id: fetchTextId, text: modifiedString.string)
}
Strikethrough -
if textStrikethrough == true {
text_View.sizeToFit()
let string = text
let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: string)
attributeString.addAttribute(NSAttributedString.Key.strikethroughStyle, value: 2, range: NSMakeRange(0, attributeString.length))
self.modifiedString = attributeString
text_View.attributedText = modifiedString
databaseHandlerObj.editLabelData(textProjectId: fetchTextProjectId, text_Id: fetchTextId, text: modifiedString.string)
}
您需要使用 NSMutableAttributedString
。在它上面,您可以使用 removeAttribute(_ name: NSAttributedString.Key, range: NSRange)
方法来指定范围,例如要删除属性的整个字符串。
您需要枚举 NSAttributedString
上的属性,并更改或删除它们。
有一点帮助from another question to know if a font is bold/italic
extension UIFont {
var isBold: Bool {
return fontDescriptor.symbolicTraits.contains(.traitBold)
}
var isItalic: Bool {
return fontDescriptor.symbolicTraits.contains(.traitItalic)
}
}
为了简化“你的真实逻辑”:
extension NSAttributedString {
enum Effects {
case bold
case italic
case underline
case strikethrough
}
var fullRange: NSRange {
NSRange(location: 0, length: length)
}
}
这应该可以解决问题:
func remove(effects: NSAttributedString.Effects, on attributedString: NSAttributedString, range: NSRange) -> NSAttributedString {
let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString)
mutableAttributedString.enumerateAttributes(in: range, options: []) { attributes, subrange, pointee in
switch effects {
case .bold:
if let currentFont = attributes[.font] as? UIFont, currentFont.isBold {
let newFont = UIFont.systemFont(ofSize: currentFont.pointSize)
// Since we can only have one attribute at a range (and all subranges including in it)
// there is no need to remove then add, adding it will replace the previous one
mutableAttributedString.addAttribute(.font, value: newFont, range: subrange)
}
case .italic:
if let currentFont = attributes[.font] as? UIFont, currentFont.isItalic {
let newFont = UIFont.systemFont(ofSize: currentFont.pointSize)
// Since we can only have one attribute at a range (and all subranges including in it)
// there is no need to remove then add, adding it will replace the previous one
mutableAttributedString.addAttribute(.font, value: newFont, range: subrange)
}
case .strikethrough:
if attributes[.strikethroughStyle] != nil {
mutableAttributedString.removeAttribute(.strikethroughStyle, range: subrange)
}
if attributes[.strikethroughColor] != nil {
mutableAttributedString.removeAttribute(.strikethroughColor, range: subrange)
}
case .underline:
if attributes[.underlineColor] != nil {
mutableAttributedString.removeAttribute(.underlineColor, range: subrange)
}
if attributes[.underlineStyle] != nil {
mutableAttributedString.removeAttribute(.underlineStyle, range: subrange)
}
}
}
return mutableAttributedString
}
在 Playground 中,您可以使用以下方法进行测试:
let boldText = NSAttributedString(string: "Bold text", attributes: [.font: UIFont.boldSystemFont(ofSize: 25)])
let unboldText = remove(effects: .bold, on: boldText, range: boldText.fullRange)
let italicText = NSAttributedString(string: "Italic text", attributes: [.font: UIFont.italicSystemFont(ofSize: 25)])
let unItalicText = remove(effects: .italic, on: italicText, range: italicText.fullRange)
let underlineText = NSAttributedString(string: "Underline text", attributes: [.underlineStyle: 1])
let unUnderlineText = remove(effects: .underline, on: underlineText, range: underlineText.fullRange)
let strikethroughText = NSAttributedString(string: "Strikethrough text", attributes: [.strikethroughStyle: 2])
let unStrikethroughText = remove(effects: .strikethrough, on: strikethroughText, range: strikethroughText.fullRange)
let attributedStrings = [boldText, unboldText, italicText, unItalicText, underlineText, unUnderlineText, strikethroughText, unStrikethroughText]
let fullAttributedString = attributedStrings.reduce(into: NSMutableAttributedString()) {
[=13=].append(NSAttributedString(string: "\n"))
[=13=].append()
}
The following test is to ensure that if there are other effects on the `NSAttributedString`, they aren't removed.
let textView = UITextView(frame: CGRect(x: 0, y: 0, width: 500, height: 200))
textView.backgroundColor = .yellow
textView.attributedText = fullAttributedString
textView
textView.attributedText = remove(effects: .bold, on: fullAttributedString, range: fullAttributedString.fullRange)
textView
textView.attributedText = remove(effects: .italic, on: fullAttributedString, range: fullAttributedString.fullRange)
textView
textView.attributedText = remove(effects: .underline, on: fullAttributedString, range: fullAttributedString.fullRange)
textView
textView.attributedText = remove(effects: .strikethrough, on: fullAttributedString, range: fullAttributedString.fullRange)
textView
注意事项:
您目前正在使用粗体或斜体,而不是同时使用两者,因为它在 属性 中位于 UIFont
内,您需要同时找到粗体和斜体字体。
所以如果你想从斜体和粗体中删除斜体,你需要得到粗体。我认为它是另一个范围,但对此有疑问。
注意事项 2:
当你想删除属性时,我检查属性是否存在,但没有必要:
所以:
if attributes[.someAttribute] != nil {
mutableAttributedString.removeAttribute(.someAttribute, range: subrange)
}
可能只是:
mutableAttributedString.removeAttribute(.someAttribute, range: subrange)
注意事项 3:
func remove(effects: NSAttributedString.Effects, on attributedString: NSAttributedString, range: NSRange) -> NSAttributedString
可以改为 NSAttributedString
/NSMutableAttributedString
的扩展。
我想删除属性字符串值并使其显示为普通字符串。 (粗体、斜体、下划线、删除线)
我添加了下面的代码以使其具有属性,但我想知道如何在再次单击该操作时从字符串中删除这些属性。
Bold -
if textBold == true {
let string = text
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.boldSystemFont(ofSize: 25)
]
let attributedString = NSAttributedString(string: string, attributes: attributes)
modifiedString = attributedString
text_View.attributedText = modifiedString
text_View.sizeToFit()
databaseHandlerObj.editLabelData(textProjectId: fetchTextProjectId, text_Id: fetchTextId, text: modifiedString.string)
}
Italic -
if textItalic == true {
text_View.sizeToFit()
let string = text
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.italicSystemFont(ofSize: CGFloat(fontSize))
]
let attributedString = NSAttributedString(string: string, attributes: attributes)
self.modifiedString = attributedString
text_View.attributedText = modifiedString
databaseHandlerObj.editLabelData(textProjectId: fetchTextProjectId, text_Id: fetchTextId, text: modifiedString.string)
}
Underline -
if textUnderline == true {
text_View.sizeToFit()
let string = text
let attributedString = NSMutableAttributedString.init(string: string)
attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: 1, range:
NSRange.init(location: 0, length: attributedString.length))
self.modifiedString = attributedString
text_View.attributedText = modifiedString
databaseHandlerObj.editLabelData(textProjectId: fetchTextProjectId, text_Id: fetchTextId, text: modifiedString.string)
}
Strikethrough -
if textStrikethrough == true {
text_View.sizeToFit()
let string = text
let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: string)
attributeString.addAttribute(NSAttributedString.Key.strikethroughStyle, value: 2, range: NSMakeRange(0, attributeString.length))
self.modifiedString = attributeString
text_View.attributedText = modifiedString
databaseHandlerObj.editLabelData(textProjectId: fetchTextProjectId, text_Id: fetchTextId, text: modifiedString.string)
}
您需要使用 NSMutableAttributedString
。在它上面,您可以使用 removeAttribute(_ name: NSAttributedString.Key, range: NSRange)
方法来指定范围,例如要删除属性的整个字符串。
您需要枚举 NSAttributedString
上的属性,并更改或删除它们。
有一点帮助from another question to know if a font is bold/italic
extension UIFont {
var isBold: Bool {
return fontDescriptor.symbolicTraits.contains(.traitBold)
}
var isItalic: Bool {
return fontDescriptor.symbolicTraits.contains(.traitItalic)
}
}
为了简化“你的真实逻辑”:
extension NSAttributedString {
enum Effects {
case bold
case italic
case underline
case strikethrough
}
var fullRange: NSRange {
NSRange(location: 0, length: length)
}
}
这应该可以解决问题:
func remove(effects: NSAttributedString.Effects, on attributedString: NSAttributedString, range: NSRange) -> NSAttributedString {
let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString)
mutableAttributedString.enumerateAttributes(in: range, options: []) { attributes, subrange, pointee in
switch effects {
case .bold:
if let currentFont = attributes[.font] as? UIFont, currentFont.isBold {
let newFont = UIFont.systemFont(ofSize: currentFont.pointSize)
// Since we can only have one attribute at a range (and all subranges including in it)
// there is no need to remove then add, adding it will replace the previous one
mutableAttributedString.addAttribute(.font, value: newFont, range: subrange)
}
case .italic:
if let currentFont = attributes[.font] as? UIFont, currentFont.isItalic {
let newFont = UIFont.systemFont(ofSize: currentFont.pointSize)
// Since we can only have one attribute at a range (and all subranges including in it)
// there is no need to remove then add, adding it will replace the previous one
mutableAttributedString.addAttribute(.font, value: newFont, range: subrange)
}
case .strikethrough:
if attributes[.strikethroughStyle] != nil {
mutableAttributedString.removeAttribute(.strikethroughStyle, range: subrange)
}
if attributes[.strikethroughColor] != nil {
mutableAttributedString.removeAttribute(.strikethroughColor, range: subrange)
}
case .underline:
if attributes[.underlineColor] != nil {
mutableAttributedString.removeAttribute(.underlineColor, range: subrange)
}
if attributes[.underlineStyle] != nil {
mutableAttributedString.removeAttribute(.underlineStyle, range: subrange)
}
}
}
return mutableAttributedString
}
在 Playground 中,您可以使用以下方法进行测试:
let boldText = NSAttributedString(string: "Bold text", attributes: [.font: UIFont.boldSystemFont(ofSize: 25)])
let unboldText = remove(effects: .bold, on: boldText, range: boldText.fullRange)
let italicText = NSAttributedString(string: "Italic text", attributes: [.font: UIFont.italicSystemFont(ofSize: 25)])
let unItalicText = remove(effects: .italic, on: italicText, range: italicText.fullRange)
let underlineText = NSAttributedString(string: "Underline text", attributes: [.underlineStyle: 1])
let unUnderlineText = remove(effects: .underline, on: underlineText, range: underlineText.fullRange)
let strikethroughText = NSAttributedString(string: "Strikethrough text", attributes: [.strikethroughStyle: 2])
let unStrikethroughText = remove(effects: .strikethrough, on: strikethroughText, range: strikethroughText.fullRange)
let attributedStrings = [boldText, unboldText, italicText, unItalicText, underlineText, unUnderlineText, strikethroughText, unStrikethroughText]
let fullAttributedString = attributedStrings.reduce(into: NSMutableAttributedString()) {
[=13=].append(NSAttributedString(string: "\n"))
[=13=].append()
}
The following test is to ensure that if there are other effects on the `NSAttributedString`, they aren't removed.
let textView = UITextView(frame: CGRect(x: 0, y: 0, width: 500, height: 200))
textView.backgroundColor = .yellow
textView.attributedText = fullAttributedString
textView
textView.attributedText = remove(effects: .bold, on: fullAttributedString, range: fullAttributedString.fullRange)
textView
textView.attributedText = remove(effects: .italic, on: fullAttributedString, range: fullAttributedString.fullRange)
textView
textView.attributedText = remove(effects: .underline, on: fullAttributedString, range: fullAttributedString.fullRange)
textView
textView.attributedText = remove(effects: .strikethrough, on: fullAttributedString, range: fullAttributedString.fullRange)
textView
注意事项:
您目前正在使用粗体或斜体,而不是同时使用两者,因为它在 属性 中位于 UIFont
内,您需要同时找到粗体和斜体字体。
所以如果你想从斜体和粗体中删除斜体,你需要得到粗体。我认为它是另一个范围,但对此有疑问。
注意事项 2:
当你想删除属性时,我检查属性是否存在,但没有必要:
所以:
if attributes[.someAttribute] != nil {
mutableAttributedString.removeAttribute(.someAttribute, range: subrange)
}
可能只是:
mutableAttributedString.removeAttribute(.someAttribute, range: subrange)
注意事项 3:
func remove(effects: NSAttributedString.Effects, on attributedString: NSAttributedString, range: NSRange) -> NSAttributedString
可以改为 NSAttributedString
/NSMutableAttributedString
的扩展。