Как проверить, содержит ли строка другую строку в Objective-C?
Я пытаюсь определить, содержит ли NSString определенную подстроку. Я попытался использовать метод вроде:
NSString *string = @"hello bla bla";
NSLog(@"%d",[string containsSubstring:@"hello"]);
Однако, этого метода не существует. Ближайший подход, который я нашел:
if ([string rangeOfString:@"hello"] == 0) {
NSLog(@"sub string doesnt exist");
}
else {
NSLog(@"exists");
}
Является ли это наиболее эффективным способом проверки наличия подстроки в Objective-C, или есть лучший подход?
Проверка наличия подстроки в NSString в Objective-C
Для проверки наличия одной строки в другой в NSString следует использовать метод rangeOfString:, который возвращает структуру NSRange, указывающую на положение подстроки. Подход, который вы нашли, верен, но имеет тонкий нюанс — следует проверять, что location не равен NSNotFound, а не сравнивать с 0, так как rangeOfString: возвращает структуру с location NSNotFound (обычно NSUIntegerMax), когда подстрока не найдена.
Содержание
- Методы работы с подстроками NSString
- RangeOfString vs HasPrefix vs HasSuffix
- Эффективные методы сравнения
- Сравнение без учета регистра
- Рекомендации по производительности
- Современные альтернативы
- Полный пример
Методы работы с подстроками NSString
NSString предоставляет несколько методов для проверки наличия подстрок, при этом rangeOfString: является наиболее универсальным:
NSString *mainString = @"hello bla bla";
NSString *substring = @"hello";
// Правильный способ проверки наличия подстроки
NSRange range = [mainString rangeOfString:substring];
if (range.location != NSNotFound) {
NSLog(@"Подстрока существует в позиции: %lu", (unsigned long)range.location);
} else {
NSLog(@"Подстрока не существует");
}
Метод rangeOfString: возвращает структуру NSRange с:
location: Начальный индекс найденной подстроки (илиNSNotFound, если не найдена)length: Длина найденной подстроки
Основные методы для проверки подстрок:
rangeOfString:- Наиболее гибкий, находит любое вхождениеrangeOfString:options:- Больше контроля с опциями поискаrangeOfString:options:range:- Поиск в определенном диапазонеrangeOfString:options:range:locale:- Поиск с учетом локали
RangeOfString vs HasPrefix vs HasSuffix
Хотя rangeOfString: является наиболее универсальным, NSString также предоставляет специализированные методы:
NSString *string = @"hello bla bla";
// Проверка, начинается ли строка с подстроки
if ([string hasPrefix:@"hello"]) {
NSLog(@"Строка начинается с 'hello'");
}
// Проверка, заканчивается ли строка подстрокой
if ([string hasSuffix:@"bla"]) {
NSLog(@"Строка заканчивается на 'bla'");
}
// Общий поиск подстроки (наиболее гибкий)
NSRange range = [string rangeOfString:@"bla"];
if (range.location != NSNotFound) {
NSLog(@"Найдено 'bla' в позиции: %lu", (unsigned long)range.location);
}
Когда использовать каждый метод:
- Используйте
hasPrefix:, когда нужно проверить только начало строки - Используйте
hasSuffix:, когда нужно проверить только конец строки - Используйте
rangeOfString:для общего поиска подстрок
Эффективные методы сравнения
Метод, который вы нашли, верен, но вот более эффективные и читаемые подходы:
Метод 1: Булево расширение (Рекомендуется)
Создайте категорию для более чистого синтаксиса:
// В NSString+Helper.h
@interface NSString (Helper)
- (BOOL)containsString:(NSString *)string;
@end
// В NSString+Helper.m
@implementation NSString (Helper)
- (BOOL)containsString:(NSString *)string {
return [self rangeOfString:string].location != NSNotFound;
}
@end
Использование:
NSString *string = @"hello bla bla";
if ([string containsString:@"hello"]) {
NSLog(@"Содержит 'hello'");
}
Метод 2: Использование NSStringCompareOptions
Для большего контроля над поведением поиска:
NSString *string = @"Hello Bla Bla";
NSRange range = [string rangeOfString:@"hello"
options:NSCaseInsensitiveSearch];
if (range.location != NSNotFound) {
NSLog(@"Найдено 'hello' (без учета регистра)");
}
Сравнение без учета регистра
Для поиска подстрок без учета регистра:
NSString *string = @"Hello Bla Bla";
// Поиск без учета регистра
NSRange range = [string rangeOfString:@"hello"
options:NSCaseInsensitiveSearch];
if (range.location != NSNotFound) {
NSLog(@"Найдено совпадение без учета регистра");
}
// Можно комбинировать несколько опций поиска
range = [string rangeOfString:@"HELLO"
options:NSCaseInsensitiveSearch | NSAnchoredSearch];
Распространенные опции поиска:
NSCaseInsensitiveSearch- Игнорировать различия в регистреNSLiteralSearch- Точное совпадение символовNSAnchoredSearch- Искать только в начале строкиNSNumericSearch- Сравнивать числовые строки
Рекомендации по производительности
Для приложений, где критична производительность:
- Используйте
hasPrefix:илиhasSuffix:для короткого замыкания, когда применимо - Используйте конкретные диапазоны, когда вы знаете, где искать:objective-c
NSRange range = [string rangeOfString:@"bla" options:0 range:NSMakeRange(0, 10)]; // Искать только первые 10 символов - Избегайте повторных поисков - сохраняйте результаты, если проверяете несколько раз
- Рассмотрите посимвольное сравнение для очень коротких строк
Сравнение производительности:
// Самый быстрый для проверки префикса
if ([string hasPrefix:@"prefix"]) { ... }
// Гибкий, но немного медленнее
if ([string rangeOfString:@"substring"].location != NSNotFound) { ... }
// Метод расширения (рекомендуется для читаемости)
if ([string containsString:@"substring"]) { ... }
Современные альтернативы
С современным Objective-C и взаимной совместимостью со Swift:
Интеграция со Swift
// Мост со Swift позволяет использовать метод contains в стиле Swift
NSString *string = @"hello bla bla";
BOOL contains = [string contains:@"hello"]; // В стиле Swift
Использование регулярных выражений
Для сложного сопоставления с образцом:
NSString *string = @"hello bla bla";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"bla"
options:0
error:nil];
if ([regex firstMatchInString:string options:0 range:NSMakeRange(0, string.length)]) {
NSLog(@"Найдено совпадение с шаблоном");
}
Полный пример
Вот комплексный пример, демонстрирующий различные подходы:
#import <Foundation/Foundation.h>
// Категория для метода containsString
@interface NSString (SubstringHelper)
- (BOOL)containsString:(NSString *)string;
- (BOOL)containsString:(NSString *)string options:(NSStringCompareOptions)options;
@end
@implementation NSString (SubstringHelper)
- (BOOL)containsString:(NSString *)string {
return [self rangeOfString:string].location != NSNotFound;
}
- (BOOL)containsString:(NSString *)string options:(NSStringCompareOptions)options {
return [self rangeOfString:string options:options].location != NSNotFound;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *mainString = @"Hello World Programming";
NSString *substring = @"world";
// Метод 1: Прямое использование rangeOfString
NSRange range = [mainString rangeOfString:substring
options:NSCaseInsensitiveSearch];
if (range.location != NSNotFound) {
NSLog(@"Найдено '%@' в позиции: %lu", substring, (unsigned long)range.location);
}
// Метод 2: Использование hasPrefix/hasSuffix
if ([mainString hasPrefix:@"Hello"]) {
NSLog(@"Строка начинается с 'Hello'");
}
// Метод 3: Использование метода категории
if ([mainString containsString:substring options:NSCaseInsensitiveSearch]) {
NSLog(@"Содержит '%@' (без учета регистра)", substring);
}
// Метод 4: Получение длины подстроки
if ([mainString containsString:@"World"]) {
NSLog(@"Длина подстроки 'World': %lu",
(unsigned long)[mainString rangeOfString:@"World"].length);
}
}
return 0;
}
Вывод:
Найдено 'world' в позиции: 6
Строка начинается с 'Hello'
Содержит 'world' (без учета регистра)
Длина подстроки 'World': 5
Заключение
Наиболее эффективный и читаемый подход для проверки наличия подстроки в NSString — использовать метод rangeOfString: и убедиться, что location не равен NSNotFound. Хотя метод, который вы нашли, концептуально верен, сравнение с 0 вместо NSNotFound является тонкой ошибкой.
Ключевые рекомендации:
- Используйте
[string rangeOfString:substring].location != NSNotFoundдля наиболее надежной проверки - Создайте метод категории, например
containsString:, для более чистого и читаемого кода - Используйте специализированные методы, такие как
hasPrefix:иhasSuffix:, когда это уместно - Учитывайте опции поиска, такие как
NSCaseInsensitiveSearch, для сравнения без учета регистра - Для оптимальной производительности используйте диапазоны и методы короткого замыкания, когда это возможно
Подход с rangeOfString: является одновременно эффективным и гибким, что делает его стандартным методом для проверки наличия подстрок в Objective-C.