如何将 NSAttributedString 中的字符大小写更改为大写

问题描述 投票:0回答:2

我想将包含RTFD的NSAttributedString转换为大写,而不丢失现有字符和图形的属性。

谢谢,

cocoa character uppercase nsattributedstring
2个回答
13
投票

编辑:

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

它的作用:

  1. 制作输入属性字符串的可变副本。
  2. 从该字符串中获取所有属性并将它们放入一个数组中,以便稍后使用。
  3. 使用内置
    NSString
    方法创建大写纯字符串。
  4. 重新应用所有属性。


0
投票

当您大写德语“ß”字符时,它会变成“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
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.