NSString:从字符串中删除UTF-8重音的简单方法?

时间:2012-06-07 13:06:02

标签: objective-c utf-8 nsstring

我想更改一个句子,例如:

  

Êtreou nepasêtre。 C'étaitlà-bas。

会变成:

  

Etre ou ne pas etre。 C'etait la-bas。

使用NSString有没有简单的方法呢?或者我是否必须通过检查每个字符来自行开发?

8 个答案:

答案 0 :(得分:57)

NSString *str = @"Être ou ne pas être. C'était là-bas.";
NSData *data = [str dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *newStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@"%@", newStr);

...或尝试改为使用NSUTF8StringEncoding

此处的编码类型列表:

https://developer.apple.com/documentation/foundation/nsstringencoding


Just FTR这里是一个单行的方式来写这个伟大的答案:

yourString = [[NSString alloc]
  initWithData:
    [yourString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]
  encoding:NSASCIIStringEncoding];

答案 1 :(得分:48)

Mattt Thompson在NSHipsterWWDC 2013 session 228

再次报道此事

TL; DR

NSMutableString *str = [@"Être ou ne pas être. C'était là-bas." mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)string, NULL, kCFStringTransformStripCombiningMarks, NO);

应该做的伎俩,对我来说很有用。

<强>买者 由于评论中有很多人说这应该是接受的答案,我想对这种方法提出一个警告。这种方法非常慢,如果需要转换大量的字符串/数据,应该小心使用

答案 2 :(得分:25)

你试过吗

[string stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:[NSLocale currentLocale]]

Boolean CFStringTransform (
   CFMutableStringRef string,
   CFRange *range,
   CFStringRef transform,
   Boolean reverse
);

CFStringTransform&amp; Transform Identifiers

NSMutableString *string = ...;
CFMutableStringRef stringRef = (__bridge CFMutableStringRef)string;
CFStringTransform(stringRef, NULL, kCFStringTransformToLatin, NO);
NSLog(@"%@", string);

答案 3 :(得分:15)

只是更新说它可以在swift中完成:

"Être ou ne pas être. C'était là-bas.".stringByFoldingWithOptions(NSStringCompareOptions.DiacriticInsensitiveSearch, locale: NSLocale.currentLocale())

- &GT; “Etre ou ne pas etre.C'etait la-bas。”

答案 4 :(得分:9)

这里使用Swift 2.0在iPhone 6 iOS 9.0模拟器上使用Swift 2.0进行性能测试:

  • CFStringTransform(任务1)
  • stringByFoldingWithOptions(任务2)

任务2始终更快,例如:

Task 1 took 9.49736100435257 seconds.
Task 2 took 1.96649599075317 seconds.

这里测试:

    let timer = ParkBenchTimer()
    for _ in 1...1000000 {
        let mStringRef = NSMutableString(string: "Être ou ne pas être. C'était là-bas.") as CFMutableStringRef
        CFStringTransform(mStringRef, nil, kCFStringTransformStripCombiningMarks, false)
        String(mStringRef)
    }
    print("Task 1 took \(timer.stop()) seconds.")

    let timer2 = ParkBenchTimer()
    for _ in 1...1000000 {
        "Être ou ne pas être. C'était là-bas.".stringByFoldingWithOptions(NSStringCompareOptions.DiacriticInsensitiveSearch, locale: NSLocale.currentLocale())
    }
    print("Task 2 took \(timer2.stop()) seconds.")

Klaas的ParkBenchTimer:https://stackoverflow.com/a/26578191/1097106

答案 5 :(得分:4)

Swift 3 (在游乐场测试)

//String+StripCombiningMarks.swift

extension String {
    /// strip combining marks (accents or diacritics)
    var stripCombiningMarks: String {
        let mStringRef = NSMutableString(string: self) as CFMutableString
        CFStringTransform(mStringRef, nil, kCFStringTransformStripCombiningMarks, false)
        return mStringRef as String
    }
}

用法:

let umlaut = "äöüÄÖÜ" //ÄÖÜ
let stripped = umlaut.stripCombiningMarks //aouAOU

答案 6 :(得分:3)

这里是完整的代码。 使用函数stringbyfoldignWithOptions。

NSString *str1=@"Être ou ne pas être C'était là-bas"; NSString *str2=[str1 stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:[NSLocale systemLocale]]; NSLog(@"%@",str2);

答案 7 :(得分:1)

对于那些想要Swift版本的CFStringTransform解决方案的人:

let stripAccentAndDiacritics: (String) -> String = {
    var mStringRef = NSMutableString(string: $0) as CFMutableStringRef
    CFStringTransform(mStringRef, nil, kCFStringTransformStripCombiningMarks, Boolean(0))
    return String(mStringRef)
}