我想将包含RTFD的NSAttributedString转换为大写,而不丢失现有字符和图形的属性。
谢谢,
编辑:
@fluidsonic 正确的是原始代码不正确。下面是 Swift 的更新版本,它将每个属性范围中的文本替换为该范围内字符串的大写版本。
extension NSAttributedString {
func uppercased() -> NSAttributedString {
let result = NSMutableAttributedString(attributedString: self)
result.enumerateAttributes(in: NSRange(location: 0, length: length), options: []) {_, range, _ in
result.replaceCharacters(in: range, with: (string as NSString).substring(with: range).uppercased())
}
return result
}
}
原答案:
- (NSAttributedString *)upperCaseAttributedStringFromAttributedString:(NSAttributedString *)inAttrString {
// Make a mutable copy of your input string
NSMutableAttributedString *attrString = [inAttrString mutableCopy];
// Make an array to save the attributes in
NSMutableArray *attributes = [NSMutableArray array];
// Add each set of attributes to the array in a dictionary containing the attributes and range
[attrString enumerateAttributesInRange:NSMakeRange(0, [attrString length]) options:0 usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
[attributes addObject:@{@"attrs":attrs, @"range":[NSValue valueWithRange:range]}];
}];
// Make a plain uppercase string
NSString *string = [[attrString string]uppercaseString];
// Replace the characters with the uppercase ones
[attrString replaceCharactersInRange:NSMakeRange(0, [attrString length]) withString:string];
// Reapply each attribute
for (NSDictionary *attribute in attributes) {
[attrString setAttributes:attribute[@"attrs"] range:[attribute[@"range"] rangeValue]];
}
return attrString;
}
它的作用:
NSString
方法创建大写纯字符串。当您大写德语“ß”字符时,它会变成“SS”;因此范围发生变化。这可能会导致接受的答案崩溃。这也是我对这个案例的建议:
extension NSAttributedString {
func uppercased() -> NSAttributedString {
// Original NSAttributedString
let originalAttributedString = self
// Convert the attributed string to a regular string
let originalString = originalAttributedString.string
// Uppercase the string
let uppercasedString = originalString.uppercased()
// Create a new mutable attributed string with the uppercased string
let uppercasedAttributedString = NSMutableAttributedString(string: uppercasedString)
// Track the difference in length due to character count changes
var indexOffset = 0
originalAttributedString.enumerateAttributes(in: NSRange(location: 0, length: length),
options: []) { attributes, range, _ in
// Extract the substring from the original string for this range
let originalSubstring = originalAttributedString.attributedSubstring(from: range).string
// Uppercase the substring
let uppercasedSubstring = originalSubstring.uppercased()
// Calculate the difference in length between the original and uppercased substrings
let lengthDifference = uppercasedSubstring.count - originalSubstring.count
// Adjust the range for the uppercased string (apply indexOffset before adjustment)
let adjustedRange = NSRange(location: range.location + indexOffset, length: uppercasedSubstring.count)
// Apply attributes to the new range in the uppercased attributed string
uppercasedAttributedString.addAttributes(attributes, range: adjustedRange)
// Update the index offset for future ranges
indexOffset += lengthDifference
}
return uppercasedAttributedString
}
}