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 } } }