I want to replace a substring (e.g. @\"replace\"
) of an NSAttributedString
with another NSAttributedString
.
I am looking for a
I had to bold text in <b>
tags, here what I've done:
- (NSAttributedString *)boldString:(NSString *)string {
UIFont *boldFont = [UIFont boldSystemFontOfSize:14];
NSMutableAttributedString *attributedDescription = [[NSMutableAttributedString alloc] initWithString:string];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@".*?<b>(.*?)<\\/b>.*?" options:NSRegularExpressionCaseInsensitive error:NULL];
NSArray *myArray = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)] ;
for (NSTextCheckingResult *match in myArray) {
NSRange matchRange = [match rangeAtIndex:1];
[attributedDescription addAttribute:NSFontAttributeName value:boldFont range:matchRange];
}
while ([attributedDescription.string containsString:@"<b>"] || [attributedDescription.string containsString:@"</b>"]) {
NSRange rangeOfTag = [attributedDescription.string rangeOfString:@"<b>"];
[attributedDescription replaceCharactersInRange:rangeOfTag withString:@""];
rangeOfTag = [attributedDescription.string rangeOfString:@"</b>"];
[attributedDescription replaceCharactersInRange:rangeOfTag withString:@""];
}
return attributedDescription;
}
I find that all of the other answers does not work. Here is how I replaced content of a NSAttributed string in a category extension:
func stringWithString(stringToReplace:String, replacedWithString newStringPart:String) -> NSMutableAttributedString
{
let mutableAttributedString = mutableCopy() as! NSMutableAttributedString
let mutableString = mutableAttributedString.mutableString
while mutableString.containsString(stringToReplace) {
let rangeOfStringToBeReplaced = mutableString.rangeOfString(stringToReplace)
mutableAttributedString.replaceCharactersInRange(rangeOfStringToBeReplaced, withString: newStringPart)
}
return mutableAttributedString
}
With Swift 4 and iOS 11, you can use one of the 2 following ways in order to solve your problem.
NSMutableAttributedString
replaceCharacters(in:with:)
methodNSMutableAttributedString
has a method called replaceCharacters(in:with:). replaceCharacters(in:with:)
has the following declaration:
Replaces the characters and attributes in a given range with the characters and attributes of the given attributed string.
func replaceCharacters(in range: NSRange, with attrString: NSAttributedString)
The Playground code below shows how to use replaceCharacters(in:with:)
in order to replace a substring of an NSMutableAttributedString
instance with a new NSMutableAttributedString
instance:
import UIKit
// Set initial attributed string
let initialString = "This is the initial string"
let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red]
let mutableAttributedString = NSMutableAttributedString(string: initialString, attributes: attributes)
// Set new attributed string
let newString = "new"
let newAttributes = [NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue]
let newAttributedString = NSMutableAttributedString(string: newString, attributes: newAttributes)
// Get range of text to replace
guard let range = mutableAttributedString.string.range(of: "initial") else { exit(0) }
let nsRange = NSRange(range, in: mutableAttributedString.string)
// Replace content in range with the new content
mutableAttributedString.replaceCharacters(in: nsRange, with: newAttributedString)
NSMutableString
replaceOccurrences(of:with:options:range:)
methodNSMutableString
has a method called replaceOccurrences(of:with:options:range:). replaceOccurrences(of:with:options:range:)
has the following declaration:
Replaces all occurrences of a given string in a given range with another given string, returning the number of replacements.
func replaceOccurrences(of target: String, with replacement: String, options: NSString.CompareOptions = [], range searchRange: NSRange) -> Int
The Playground code below shows how to use replaceOccurrences(of:with:options:range:)
in order to replace a substring of an NSMutableAttributedString
instance with a new NSMutableAttributedString
instance:
import UIKit
// Set initial attributed string
let initialString = "This is the initial string"
let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red]
let mutableAttributedString = NSMutableAttributedString(string: initialString, attributes: attributes)
// Set new string
let newString = "new"
// Replace replaceable content in mutableAttributedString with new content
let totalRange = NSRange(location: 0, length: mutableAttributedString.string.count)
_ = mutableAttributedString.mutableString.replaceOccurrences(of: "initial", with: newString, options: [], range: totalRange)
// Get range of text that requires new attributes
guard let range = mutableAttributedString.string.range(of: newString) else { exit(0) }
let nsRange = NSRange(range, in: mutableAttributedString.string)
// Apply new attributes to the text matching the range
let newAttributes = [NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue]
mutableAttributedString.setAttributes(newAttributes, range: nsRange)