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

Objective c NSString:从字符串中删除UTF-8重音的简单方法?,objective-c,utf-8,nsstring,Objective C,Utf 8,Nsstring,我想更改一个句子,例如: Être ou ne pasêtre。塞泰特·拉巴斯 将成为: 你真是太好了。这是我的生日 有什么简单的方法可以使用NSString实现这一点吗?或者我必须通过检查每个字符来自己开发这个吗?你试过了吗 [string stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:[NSLocale currentLocale]] 或 ? & 。。。或者尝试改用NSUTF8StringEncoding 此处

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

Être ou ne pasêtre。塞泰特·拉巴斯

将成为:

你真是太好了。这是我的生日

有什么简单的方法可以使用NSString实现这一点吗?或者我必须通过检查每个字符来自己开发这个吗?

你试过了吗

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

?

&

。。。或者尝试改用
NSUTF8StringEncoding

此处的编码类型列表:


这是一个写下这个伟大答案的单行方法:

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

马特·汤普森在一次又一次的演讲中谈到了这一点

TL;博士

如果我能做到这一点,那对我来说效果很好

警告
因为很多人在评论中说这应该是公认的答案,所以我想对这种方法提出警告。此方法非常慢,如果需要转换大量字符串/数据,应小心使用此方法

只是更新一下,说明可以像在swift中那样完成:

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

-->“Etre ou ne pas Etre.C'etait la bas.”

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

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

以下是在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:

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

NSString*str1=@“你是我的朋友”;
NSString*str2=[str1 stringByFoldingWithOptions:NSDIACRITICINCINSENSTIVESEARCH
语言环境:[NSLocale systemLocale]];
NSLog(@“%@”,str2)

Swift 3(在操场上测试)

用法:

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

谢谢,但是当我转换UTF-8字符时,例如,a不会变成but?编辑的帖子-抱歉,我使用了错误的编码类型。我的使用ASCII编码的版本在Xcode中工作-也许使用正确的编码对您有效。这似乎假设字符串可以转换为ASCII而不会丢失信息(除了重音)。对于本例可能有效,但在其他字符集中使用语言时远不能保证有效。@vomako您要转换为数据的字符串可能为零-代码在iOS 8下运行良好。@vomako如果您无法解决此问题(使用谷歌和本网站!),那么我建议在此提出一个新问题,并链接到此选项和您的注释以供参考。无需中间NSData转换和UTF-8编码丢失,请参阅解决方案的更改答案。@Regexident我尝试了此操作,但无效,我在CFStringTransform上遇到错误(stringRef,NULL,KCFStringTransformorMTolatin,否);这一行……这是我发现的第二个问题,它具有将NSData转换为可接受答案的“技巧”。您的答案应该是可以接受的,它甚至超过了
[input StringByFolding with Options:NSDiacriticInsensitiveSearch locale:[NSLocale currentLocale]] nSututable字符串< /代码>。不是一个
NSString*
。回答得很好,很高兴看到更多的快速变化。感谢您回答我关于两种方法性能比较的问题!
let stripAccentAndDiacritics: (String) -> String = {
    var mStringRef = NSMutableString(string: $0) as CFMutableStringRef
    CFStringTransform(mStringRef, nil, kCFStringTransformStripCombiningMarks, Boolean(0))
    return String(mStringRef)
}
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.")
//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