2012-06-07 10 views

Odpowiedz

52
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); 

... albo spróbuj użyć NSUTF8StringEncoding zamian.

Lista typ kodowania tutaj:

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


Wystarczy FTR oto sposób jeden wiersz napisać tę wielką odpowiedź:

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

Dziękuję, ale kiedy transformuję znaki UTF-8, na przykład ** na ** nie staje się ** a **, ale **? **. – Rob

+0

Edytowany post - przepraszam Użyłem niewłaściwego typu kodowania. Moja wersja używająca kodowania ASCII działa w Xcode - może użycie właściwego kodowania zadziała. – Luke

+1

Tym razem zadziałało. Dziękuję Ci ! – Rob

20

Czy próbowałeś

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

złoto

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

?

CFStringTransform & Transform Identifiers

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

Próbowałem, ale to nie działa. Mimo wszystko dziekuję. – Rob

+0

Zobacz zmienioną odpowiedź na rozwiązanie bez potrzeby pośredniej konwersji NSData i utraty kodowania UTF-8. – Regexident

+0

To zadziałało idealnie dla mnie. –

46

Mattt Thompson to omówione w NSHipster i ponownie ma WWDC 2013 session 228

TL; DR

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

powinno załatwić sprawę, że pracował dla mnie świetnie.

Zastrzeżenie Ponieważ wielu ludzi w komentarzach powiedzieć shoulds być zaakceptowane odpowiedź chcę dać zastrzeżenie do tej metody. Metoda ta jest cholernie powolny i powinności należy stosować ostrożnie, jeśli ogromny trace ciąg/dane muszą zostać przekształcone

+2

To drugie pytanie, które znalazłem, ma "sztuczkę" do przekonwertowania na NSData iz powrotem jako zaakceptowaną odpowiedź. Twoja odpowiedź powinna być akceptowalna, nawet bije '[input stringByFoldingWithOptions: NSDiacriticInsensitiveSearch locale: [NSLocale currentLocale]] ;, w tym, że nie wymaga lokalizacji. – xorgate

+0

Dzięki, okazuje się, że jest wiele fajnych rzeczy w Core Foundation, które się zmyły. – tapi

+0

Powinna to być zatwierdzona odpowiedź i podziękowania za link do strony Mattta Thompsona. –

15

właśnie aktualizacja powiedzieć, że można zrobić tak, że SWIFT:

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

- -.> „być albo nie być było tam.”

+0

Doskonała odpowiedź i świetnie widać więcej odmian Swift. – SaltyNuts

1

Dla tych, którzy chcą uwolnienia roztworu Swift CFStringTransform

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

używał Swift Performance Test 2.0 iOS 6 na iPhone 9.0 Symulator pomiędzy rozwiązaniami z:

  • CFStringTransform (Zadanie 1)
  • stringByFoldingWithOptions (zadanie 2)

Zadanie 2 jest konsekwentnie szybciej, np

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

W tym teście:

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.") 

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

+0

Dziękuję za odpowiedź na moje pytanie dotyczące porównania wydajności dwóch metod! –

3

tutaj jest pełny kod. użyj funkcji stringbyfoldignWithOptions.

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

3

Swift 3 (testowane na placu zabaw)

//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 
    } 
} 

Zastosowanie:

let umlaut = "äöüÄÖÜ" //ÄÖÜ 
let stripped = umlaut.stripCombiningMarks //aouAOU 
Powiązane problemy