¿Cómo puedo comprobar si una cadena contiene otra cadena en Objective-C?


¿Cómo puedo comprobar si una cadena (NSString) contiene otra cadena más pequeña?

Esperaba algo como:

NSString *string = @"hello bla bla";
NSLog(@"%d",[string containsSubstring:@"hello"]);

Pero lo más cercano que pude encontrar fue:

if ([string rangeOfString:@"hello"] == 0) {
    NSLog(@"sub string doesnt exist");
} 
else {
    NSLog(@"exists");
}

De todos modos, ¿es esa la mejor manera de encontrar si una cadena contiene otra cadena?

Author: Bhavin Ramani, 2010-05-02

20 answers

NSString *string = @"hello bla bla";
if ([string rangeOfString:@"bla"].location == NSNotFound) {
  NSLog(@"string does not contain bla");
} else {
  NSLog(@"string contains bla!");
}

La clave está notando que rangeOfString: devuelve una estructura NSRange, y la documentación dice que devuelve la estructura {NSNotFound, 0} si el "pajar" no contiene la "aguja".


Y si está en iOS 8 o OS X Yosemite, ahora puede hacer: (*NOTA: Esto bloqueará su aplicación si se llama a este código en un dispositivo iOS7).

NSString *string = @"hello bla blah";
if ([string containsString:@"bla"]) {
  NSLog(@"string contains bla!");
} else {
  NSLog(@"string does not contain bla");
}

 2372
Author: Dave DeLong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-01 06:05:34

NOTA: Esta respuesta está ahora obsoleta

Crear una categoría para NSString:

@interface NSString ( SubstringSearch )
    - (BOOL)containsString:(NSString *)substring;
@end

// - - - - 

@implementation NSString ( SubstringSearch )

- (BOOL)containsString:(NSString *)substring
{    
    NSRange range = [self rangeOfString : substring];
    BOOL found = ( range.location != NSNotFound );
    return found;
}

@end

EDITAR: Observe el comentario de Daniel Galasko a continuación con respecto al nombramiento

 155
Author: P i,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-02 16:49:31

Dado que esto parece ser un resultado de alto rango en Google, quiero agregar esto:

IOS 8 y OS X 10.10 añadir el containsString: método para NSString. Una versión actualizada del ejemplo de Dave DeLong para esos sistemas:

NSString *string = @"hello bla bla";
if ([string containsString:@"bla"]) {
    NSLog(@"string contains bla!");
} else {
    NSLog(@"string does not contain bla");
}
 48
Author: Lukas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-28 07:29:40
NSString *myString = @"hello bla bla";
NSRange rangeValue = [myString rangeOfString:@"hello" options:NSCaseInsensitiveSearch];

if (rangeValue.length > 0)
{
    NSLog(@"string contains hello");
} 
else 
{
    NSLog(@"string does not contain hello!");
}

/ / También puedes usar lo siguiente :

if (rangeValue.location == NSNotFound) 
{
    NSLog(@"string does not contain hello");
} 
else 
{
    NSLog(@"string contains hello!");
}
 36
Author: AJS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-01 11:41:52

Con iOS 8 y Swift, podemos usar localizedCaseInsensitiveContainsString método

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

 string.localizedCaseInsensitiveContainsString(substring) // true
 21
Author: iGo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-08 05:10:58

Así que personalmente realmente odio NSNotFound pero entiendo su necesidad.

Pero algunas personas pueden no entender las complejidades de comparar con NSNotFound

Por ejemplo, este código:

- (BOOL)doesString:(NSString*)string containString:(NSString*)otherString {
    if([string rangeOfString:otherString].location != NSNotFound)
        return YES;
    else
        return NO;
}

Tiene sus problemas:

1) Obviamente si otherString = nil este código se bloqueará. una prueba simple sería:

NSLog(@"does string contain string - %@", [self doesString:@"hey" containString:nil] ? @"YES": @"NO");

Resultados en !! CRASH !!

2) Lo que no es tan obvio para alguien nuevo en objective-c es que el mismo código NO se bloqueará cuando string = nil. Para ejemplo, este código:

NSLog(@"does string contain string - %@", [self doesString:nil containString:@"hey"] ? @"YES": @"NO");

Y este código:

NSLog(@"does string contain string - %@", [self doesString:nil containString:nil] ? @"YES": @"NO");

Ambos resultarán en

does string contains string - YES

Que claramente NO es lo que quieres.

Así que la mejor solución que creo que funciona es usar el hecho de que rangeOfString devuelve la longitud de 0, por lo que un código mejor y más confiable es este:

- (BOOL)doesString:(NSString*)string containString:(NSString*)otherString {
    if(otherString && [string rangeOfString:otherString].length)
        return YES;
    else
        return NO;
}

O SIMPLEMENTE:

- (BOOL)doesString:(NSString*)string containString:(NSString*)otherString {
    return (otherString && [string rangeOfString:otherString].length);
}

Que para los casos 1 y 2 volverá

does string contains string - NO

Esos son mis 2 centavos; -)

Por favor, echa un vistazo a mi Gist para más código útil.

 12
Author: ucangetit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-06 07:07:48

Una versión mejorada de La solución de P i , una categoría en NSString, que no solo dirá, si una cadena se encuentra dentro de otra cadena, sino que también toma un rango por referencia, es:

@interface NSString (Contains)
-(BOOL)containsString: (NSString*)substring
              atRange:(NSRange*)range;

-(BOOL)containsString:(NSString *)substring;
@end

@implementation NSString (Contains)

-(BOOL)containsString:(NSString *)substring
              atRange:(NSRange *)range{

    NSRange r = [self rangeOfString : substring];
    BOOL found = ( r.location != NSNotFound );
    if (range != NULL) *range = r;
    return found;
}

-(BOOL)containsString:(NSString *)substring
{
    return [self containsString:substring
                        atRange:NULL];
}

@end

Úsalo como:

NSString *string = @"Hello, World!";

//If you only want to ensure a string contains a certain substring
if ([string containsString:@"ello" atRange:NULL]) {
    NSLog(@"YES");
}

// Or simply
if ([string containsString:@"ello"]) {
    NSLog(@"YES");
}

//If you also want to know substring's range
NSRange range;
if ([string containsString:@"ello" atRange:&range]) {
    NSLog(@"%@", NSStringFromRange(range));
}
 11
Author: vikingosegundo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:48

Aquí hay un fragmento de función de copiar y pegar:

-(BOOL)Contains:(NSString *)StrSearchTerm on:(NSString *)StrText
{
    return [StrText rangeOfString:StrSearchTerm 
        options:NSCaseInsensitiveSearch].location != NSNotFound;
}
 8
Author: Durai Amuthan.H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-19 05:34:21

Oneliner (Menor cantidad de código. SECA, ya que solo tienes una NSLog):

NSString *string = @"hello bla bla";
NSLog(@"String %@", ([string rangeOfString:@"bla"].location == NSNotFound) ? @"not found" : @"cotains bla"); 
 6
Author: jerik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-12 12:24:40
NSString *categoryString = @"Holiday Event";
if([categoryString rangeOfString:@"Holiday"].location == NSNotFound)
{
    //categoryString does not contains Holiday
}
else
{
    //categoryString contains Holiday
}
 5
Author: Ada,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-26 00:40:09

Prueba esto,

NSString *string = @"test Data";
if ([[string lowercaseString] rangeOfString:@"data"].location == NSNotFound) 
{
    NSLog(@"string does not contain Data");
}   
else 
{
    NSLog(@"string contains data!");
}
 4
Author: Pooja Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-11 08:18:31

Si necesita esto una vez escriba:

NSString *stringToSearchThrough = @"-rangeOfString method finds and returns the range of the first occurrence of a given string within the receiver.";
BOOL contains = [stringToSearchThrough rangeOfString:@"occurence of a given string"].location != NSNotFound;
 3
Author: Nikolay Shubenkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-24 14:00:13

En el caso de swift, se puede utilizar

let string = "Package #23"
if string.containsString("Package #") {
    //String contains substring
}
else {
    //String does not contain substring
}
 3
Author: Sreedeepkesav M S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-11 07:50:05

La mejor solución. Tan simple como esto! Si quieres encontrar una palabra o parte de la cuerda. Puedes usar este código. En este ejemplo vamos a comprobar si el valor de word contiene "acter".

NSString *word =@"find a word or character here";
if ([word containsString:@"acter"]){
    NSLog(@"It contains acter");
} else {
     NSLog (@"It does not contain acter");
}
 3
Author: handiansom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-22 07:17:24

En Swift 4:

let a = "Hello, how are you?"
a.contains("Hello")   //will return true
 3
Author: Ankit garg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-08 10:47:27

If no se preocupe por la cadena que distingue entre mayúsculas y minúsculas. Prueba esto una vez.

NSString *string  = @"Hello World!";

if([string rangeOfString:@"hello" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
    NSLog(@"found");
}
else
{
    NSLog(@"not found");
}
 2
Author: Abhijit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-01 11:41:00

Utilice este código

NSString *string = @"hello bla bla";
if ([string rangeOfString:@"bla"].location == NSNotFound) 
{
    NSLog(@"string does not contain bla");
} 
else 
{  
    NSLog(@"string contains bla!");
}
 1
Author: Rohit suvagiya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-11 08:14:40

Utilice la opción NSCaseInsensitiveSearch con rangeOfString: opciones:

NSString *me = @"toBe" ;
NSString *target = @"abcdetobe" ;
NSRange range = [target  rangeOfString: me options: NSCaseInsensitiveSearch];
NSLog(@"found: %@", (range.location != NSNotFound) ? @"Yes" : @"No");
if (range.location != NSNotFound) {
// your code
}

Se encuentra el resultado de salida: Sí

Las opciones pueden ser "or'ed" juntas e incluir:

NSCaseInsensitiveSearch NSLiteralSearch NSBackwardsSearch y más

 1
Author: iosDeveloper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-07 16:02:09

La primera cadena contiene o no la segunda cadena,

NSString *first = @"Banana";
NSString *second = @"BananaMilk";
NSRange range = [first rangeOfString:second options:NSCaseInsensitiveSearch];

if (range.length > 0) {
    NSLog(@"Detected");
}
else {
    NSLog(@"Not detected");
}
 0
Author: Kamani Jasmin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-20 00:56:21

Si se necesita cierta posición de la cadena, este código se coloca en Swift 3.0:

let string = "This is my string"
let substring = "my"

let position = string.range(of: substring)?.lowerBound
 -3
Author: pedrouan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-04 15:29:22