Випадок нечутливого порівняння NSString


240

Чи може хто-небудь вказати мені на будь-які ресурси щодо порівняння нечутливих до обставин у «Цілі C»? Схоже, він не має аналогічного методуstr1.equalsIgnoreCase(str2)

Відповіді:


564
if( [@"Some String" caseInsensitiveCompare:@"some string"] == NSOrderedSame ) {
  // strings are equal except for possibly case
}

Документація розміщена у розділі Методи пошуку та порівняння


152
Варто відзначити , що в разі , коли @"Some String"приймається від будь-якого іншого виклику і трапляється nil, ваш ifбуде давати , trueяк відправка caseInsensitiveCompareв nilкоректний і призводить до іншої , nilякий, в нашому випадку, по порівнянні з NSOrderedSameповерне true( NSOrderedSameвизначається як 0). Це може бути джерелом досить руйнівних помилок, як це було в моєму випадку. Ура!
мат.

10
Моє вирішення цього полягає в тому, щоб реалізувати це порівняння як метод всередині категорії, NSStringщо повертає булеву форму. Тоді якщо рядок прийому є nil, метод у цілому повертається NO.
Обезчерені

50
 NSString *stringA;
 NSString *stringB;

 if (stringA && [stringA caseInsensitiveCompare:stringB] == NSOrderedSame) {
     // match
 }

Примітка: stringA && потрібно , тому що , коли stringAце nil:

 stringA = nil;
 [stringA caseInsensitiveCompare:stringB] // return 0

і так трапляється NSOrderedSameтакож визначається як 0.

Наступний приклад - типовий підводний камінь:

 NSString *rank = [[NSUserDefaults standardUserDefaults] stringForKey:@"Rank"];
 if ([rank caseInsensitiveCompare:@"MANAGER"] == NSOrderedSame) {
     // what happens if "Rank" is not found in standardUserDefaults
 }

46

Альтернативою, якщо ви хочете більше контролю, ніж просто нечутливість до випадку, є:

[someString compare:otherString options:NSCaseInsensitiveSearch];

Числовий пошук та діакритична нечутливість - це два зручні варіанти.


4
Як зазначено вище у математиці, це повернеться істиною, якщо someString є нульовим.
nh32rg

@ nh32rg Не могли б ви просто компенсувати помилковий позитив, змінивши твердження if на щось на кшталтif ([someString compare:otherString options:NSCaseInsensitiveSearch] && someString.length > 0 && someString != (id)[NSNull null])
KingPolygon

1
насправді вам потрібно написати [... comapre: ...] == 0, тому що порівняйте return NSOrderSame (= 0), якщо два рядки однакові. для, someString! = (id) [NSNull null], я не думаю, що це потрібно, тому що якщо null, то довжина дорівнює нулю. Я зазвичай порівнюю так: якщо (someString.length> 0 && [someString порівняти: ortherString параметри: NSCaseIntensitiveSearch] == 0)
Tran Quan

23

Ви завжди можете переконатися, що вони є в одному випадку перед порівнянням:

if ([[stringX uppercaseString] isEqualToString:[stringY uppercaseString]]) {
    // They're equal
}

Основна вигода полягає в тому, що ви уникаєте потенційної проблеми, описаної математикою, щодо порівняння нульових рядків. Ви можете або перевірити рядок не нульовою, перш ніж виконувати один із compare:options:методів, або ви можете бути ледачим (як я) і проігнорувати додаткові витрати на створення нової рядки для кожного порівняння (що мінімально, якщо ви робите лише один або два порівняння).


3
Маніпуляція корпусом для порівняння зазвичай не є розумною справою (наприклад, тест на індичку: moserware.com/2008/02/does-your-code-pass-turkey-test.html ). Коли у вас підтримується мова порівняння випадків (наприклад caseInsensitiveCompare), завжди використовуйте це.
Охад Шнайдер

7
- (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString

12
Людям набагато корисніше, якщо відповіді мають якийсь контекст та опис.
jowie

7

Новий спосіб зробити це. iOS 8

let string: NSString = "Café"
let substring: NSString = "É"

string.localizedCaseInsensitiveContainsString(substring) // true

версія objC: if (string && [string
localizedCaseInsensitiveContainsString

ОП вимагає "Порівняння нечутливого до випадку" . Якщо ваше рішення повертається trueдля "Café" та "É", це, безумовно, НЕ є правильною відповіддю.
Олександр Абакумов

6

Спробуйте цей метод

- (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString

6

Перетворення відповіді Джейсона Коко на Свіфта для глибоко ледачих :)

if ("Some String" .caseInsensitiveCompare("some string") == .OrderedSame)
{
  // Strings are equal.
}

1
це потрібно тим, чиї XCodes відмовляються від автозаповнення! : D
Нітін Алабур

5

перевірити з префіксом, як у iPhone ContactApp

([string rangeOfString:prefixString options:NSCaseInsensitiveSearch].location == 0)

цей блог був для мене корисним


1

Альтернативне рішення для швидкого:

Щоб зробити обидві UpperCase:

наприклад:

if ("ABcd".uppercased() == "abcD".uppercased()){
}

або зробити обидва LowerCase:

наприклад:

if ("ABcd".lowercased() == "abcD".lowercased()){
}

0

На macOS можна просто використовувати -[NSString isCaseInsensitiveLike:], який повертається BOOLтак само -isEqual:.

if ([@"Test" isCaseInsensitiveLike: @"test"])
    // Success

-3
NSMutableArray *arrSearchData;  
NSArray *data=[arrNearByData objectAtIndex:i];
NSString *strValue=[NSString stringWithFormat:@"%@", [data valueForKey:@"restName"]];
NSRange r = [strValue rangeOfString:key options:NSCaseInsensitiveSearch];

if(r.location != NSNotFound)
{
     [arrSearchData addObject:data];
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.