replaceNSAttributedString中的整个文本string,而不修改其他属性
我有一个NSAttributedString
的引用,我想改变属性string的文本。
我想我必须创build一个新的NSAttributedString
和更新引用这个新的string。 但是,当我这样做,我失去了以前的string的属性。
NSAttributedString *newString = [[NSAttributedString alloc] initWithString:text]; [self setAttributedText:newString];
我在self.attributedText
引用了旧的归因string。 我怎样才能保留以前的新string中的属性?
你可以使用NSMutableAttributedString,只是更新string,属性不会改变。 例:
NSMutableAttributedString *mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:@"my string" attributes:@{NSForegroundColorAttributeName: [UIColor blueColor], NSFontAttributeName: [UIFont systemFontOfSize:20]}]; //update the string [mutableAttributedString.mutableString setString:@"my new string"];
Swift版本
在保持属性的同时更改文本:
let myString = "my string" let myAttributes = [NSForegroundColorAttributeName: UIColor.blue, NSFontAttributeName: UIFont.systemFont(ofSize: 40)] let mutableAttributedString = NSMutableAttributedString(string: myString, attributes: myAttributes) let myNewString = "my new string" mutableAttributedString.mutableString.setString(myNewString)
mutableAttributedString
的结果是
笔记
任何超出索引0的属性的子范围都将被丢弃。 例如,如果我将另一个属性添加到原始string的最后一个单词中,则在更改string后会丢失它:
// additional attribute added before changing the text let myRange = NSRange(location: 3, length: 6) let anotherAttribute = [ NSBackgroundColorAttributeName: UIColor.yellow ] mutableAttributedString.addAttributes(anotherAttribute, range: myRange)
结果:
由此我们可以看到,新的string得到了原始string的索引0处的任何属性。 事实上,如果我们调整范围
let myRange = NSRange(location: 0, length: 1)
我们得到
也可以看看
- 我关于Swift归因string的主要答案
这是使用Objective-C的方式(在iOS 9上testing)
NSAttributedString *primaryString = ...; NSString *newString = ...; //copy the attributes NSDictionary *attributes = [primaryString attributesAtIndex:0 effectiveRange:NSMakeRange(primaryString.length-1, primaryString.length)]; NSMutableAttributedString *newString = [[NSMutableAttributedString alloc] initWithString:newString attributes:attributes]; NSMutableAttributedString *primaryStringMutable = [[NSMutableAttributedString alloc] initWithAttributedString:primaryString]; //change the string [primaryStringMutable setAttributedString::newString]; primaryString = [NSAttributedString alloc] initWithAttributedString:primaryStringMutable];
检查最重要的引用: attributesAtIndex:effectiveRange:和setAttributedString:。
大stream士的回答几乎就在那里。 它包含一个小错误。 正确的是:
这是使用Objective-C的方式(在iOS 10上testing)
NSAttributedString *primaryString = ...; NSString *newString = ...; //copy the attributes NSRange range = NSMakeRange(primaryString.length-1, primaryString.length); NSDictionary *attributes = [primaryString attributesAtIndex:0 effectiveRange:&range]; NSMutableAttributedString *newString = [[NSMutableAttributedString alloc] initWithString:newString attributes:attributes]; NSMutableAttributedString *primaryStringMutable = [[NSMutableAttributedString alloc] initWithAttributedString:primaryString]; //change the string [primaryStringMutable setAttributedString::newString]; primaryString = [NSAttributedString alloc] initWithAttributedString:primaryStringMutable];
我做了一些扩展,使其变得非常简单:
import UIKit extension UILabel { func setTextWhileKeepingAttributes(string: String) { if let newAttributedText = self.attributedText { let mutableAttributedText = newAttributedText.mutableCopy() mutableAttributedText.mutableString.setString(string) self.attributedText = mutableAttributedText as? NSAttributedString } } }
https://gist.github.com/wvdk/e8992e82b04e626a862dbb991e4cbe9c
对于那些使用UIButtons的人来说,这是一个基于Wes的改进的答案。
似乎更新button的标签最好是这样做的:
let newtext = "my new text" myuibutton.setAttributedTitle(titlelabel.getTextWhileKeepingAttributes(string: newtext), for: .normal)
所以我结束了这个扩展:
import UIKit extension UILabel { func setTextWhileKeepingAttributes(string: String) { if let newAttributedText = self.attributedText { let mutableAttributedText = newAttributedText.mutableCopy() (mutableAttributedText as AnyObject).mutableString.setString(string) self.attributedText = mutableAttributedText as? NSAttributedString } } func getTextWhileKeepingAttributes(string: String) -> NSAttributedString { if let newAttributedText:NSAttributedString = self.attributedText { let mutableAttributedText = newAttributedText.mutableCopy() (mutableAttributedText as AnyObject).mutableString.setString(string) return mutableAttributedText as! NSAttributedString } else { // No attributes in this label, just create a new attributed string? let attributedstring = NSAttributedString.init(string: string) return attributedstring } } }