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

1212

¿Cómo puedo verificar 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?

Jonathan
fuente
1
También me gustaría verlo agregado, pero mientras tanto es relativamente fácil agregarlo como una categoría en NSString.
Isaac
2
Usando if ([string rangeOfString:@"hello"] == 0) {...}hay un error de desajuste de tipo para NSRange e int. para arreglar eso, debes cambiar la línea a la siguiente:if ([string rangeOfString:@"hello"].length == 0) {...}
Neeku
1
iOS 8 agrega contieneString: y aquí hay una forma mínimamente invasiva de agregar soporte para iOS 7 petersteinberger.com/blog/2014/…
Steve Moser
2
He sido desarrollador de iOS desde el principio y constantemente reviso esta publicación para copiar y pegar rápidamente. Parece que no puedo memorizar este. La publicación de stackoverflow más visitada de mi historia.
VaporwareWolf
solo use Swift;)
Fattie

Respuestas:

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

La clave es darse cuenta de que rangeOfString:devuelve una NSRangeestructura, y la documentación dice que devuelve la estructura{NSNotFound, 0} si el "pajar" no contiene la "aguja".


Y si está usando iOS 8 u 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");
}

(Así es como funcionaría en Swift)

👍

Dave DeLong
fuente
286
Para realizar una búsqueda que no distinga entre mayúsculas y minúsculas, use "if ([string rangeOfString: @" bla "options: NSCaseInsensitiveSearch] .location! = NSNotFound)"
Vanja
1
@Dave DeLong ¡Solo iba a mencionar una Categoría que creé para este propósito antes de leer tu edición con la respuesta! Como soy principalmente desarrollador ac #, me alegro de que hayan agregado un método contiene a NSSTring.
dherrin79
¿Por qué el compilador no dice nada si mi objetivo de implementación es iOS7 y utilizo contieneString?
Ricardo
3
Y para avanzar en el punto hecho por @Vanja: si va a usar el código de acceso directo [string contieneString] que se introdujo en iOS 8 / Yosemite, puede usar el siguiente código para una cadena que no distingue entre mayúsculas y minúsculas: "[stringToSearch localizedCaseInsensitiveContainsString: string ] ", y este si desea hacer un caso y una búsqueda diacrítica insensible:" [stringToSearch localizedStandardContainsString: string] ".
Scott Kohlert
1
Tenga en cuenta que la expresión [string rangeOfString:@"bla"].location != NSNotFoundserá verdadera cuando cadena es nil!
funroll
158

Para iOS 8.0+ y macOS 10.10+, puede usar el nativo de NSString containsString: .

Para versiones anteriores de iOS y macOS, puede crear su propia categoría (obsoleta) 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

Nota: Observe el comentario de Daniel Galasko a continuación sobre el nombramiento

Pi
fuente
13
+1 para un código resultante más claro y reutilización. Lo convertí en el único revestimiento return [self rangeOfString:substring].location != NSNotFound;y lo incluí en mi biblioteca de refactorización, es_ios_utils. github.com/peterdeweese/es_ios_utils
Peter DeWeese
44
Parece que a Apple le gusta tu idea y agregó esta característica en iOS 8 y OSx 10.10 (Yosemite) como @DaveDeLong mencionó en su respuesta. +1
Islam Q.
77
La regla cardinal para las categorías obj-c es prefijar el nombre del método con su prefijo de módulo de 3 letras. Este es el ejemplo perfecto ya que ahora está en conflicto con el lanzamiento de iOS 7 y 10.10
Daniel Galasko
54

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

iOS 8 y OS X 10.10 agregan el containsString:método a 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");
}
Lukas
fuente
39
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!");
}
AJS
fuente
22

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

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

 string.localizedCaseInsensitiveContainsString(substring) // true
Govind
fuente
1
Esto es bueno. No tengo idea de por qué no tenían este método para iOS 7
Lucas
@Lucas, porque Swift se lanzó con iOS 8.0. pero con
Swift
13

Personalmente, realmente odio NSNotFoundpero entiendo su necesidad.

Pero algunas personas pueden no entender las complejidades de comparar contra 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 = nileste código fallará. 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 el objetivo-c es que el mismo código NO se bloqueará cuando string = nil. Por 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.

Entonces, 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 ;-)

Consulte mi Gist para obtener más código útil.

ucangetit
fuente
12

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

Úselo 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));
}
vikingosegundo
fuente
8

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

-(BOOL)Contains:(NSString *)StrSearchTerm on:(NSString *)StrText
{
    return [StrText rangeOfString:StrSearchTerm 
        options:NSCaseInsensitiveSearch].location != NSNotFound;
}
Durai Amuthan.H
fuente
¿Puedo saber por qué me rechazan? Es un fragmento de código que funciona
Durai Amuthan. H
6

Oneliner (menor cantidad de código. SECO, ya que solo tiene uno NSLog):

NSString *string = @"hello bla bla";
NSLog(@"String %@", ([string rangeOfString:@"bla"].location == NSNotFound) ? @"not found" : @"cotains bla"); 
jerik
fuente
6
NSString *categoryString = @"Holiday Event";
if([categoryString rangeOfString:@"Holiday"].location == NSNotFound)
{
    //categoryString does not contains Holiday
}
else
{
    //categoryString contains Holiday
}
Ada
fuente
5

prueba esto,

NSString *string = @"test Data";
if ([[string lowercaseString] rangeOfString:@"data"].location == NSNotFound) 
{
    NSLog(@"string does not contain Data");
}   
else 
{
    NSLog(@"string contains data!");
}
Pooja Patel
fuente
5

Mejor solución. ¡Tan simple como esto! Si desea encontrar una palabra o parte de la cadena. Puedes usar este código. En este ejemplo vamos a verificar si el valor de la palabra 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");
}
handiansom
fuente
5

En Swift 4:

let a = "Hello, how are you?"
a.contains("Hello")   //will return true
Ankit Garg
fuente
4

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;
Nikolay Shubenkov
fuente
4

En caso de rapidez, esto se puede usar

let string = "Package #23"
if string.containsString("Package #") {
    //String contains substring
}
else {
    //String does not contain substring
}
Sreedeepkesav MS
fuente
2

Si no te preocupes por la cadena de mayúsculas y minúsculas. Intenta esto una vez.

NSString *string  = @"Hello World!";

if([string rangeOfString:@"hello" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
    NSLog(@"found");
}
else
{
    NSLog(@"not found");
}
Abhijit
fuente
1

Por favor use 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!");
}
Rohit suvagiya
fuente
1

Use 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 se pueden "or'ed" juntas e incluyen:

NSCaseInsensitiveSearch NSLiteralSearch NSBackwardsSearch y más

Nayab Muhammad
fuente
0

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");
}
Kamani Jasmin
fuente
0

Prueba esto:

Swift 4.1, 4.2:

let stringData = "Black board"

//swift quick way and case sensitive
if stringData.contains("bla") {
    print("data contains string");
}

//case sensitive
if stringData.range(of: "bla",options: .caseInsensitive) != nil {
    print("data contains string");
}else {
    print("data does not contains string");
}

Para el objetivo-C:

NSString *stringData = @"Black board";

//Quick way and case sensitive
if ([stringData containsString:@"bla"]) {
    NSLog(@"data contains string");
}

//Case Insensitive
if ([stringData rangeOfString:@"bla" options:NSCaseInsensitiveSearch].location != NSNotFound) {
   NSLog(@"data contains string");
}else {
   NSLog(@"data does not contain string");
}
Amir.n3t
fuente
0

Swift 4 y superior

let str = "Hello iam midhun"

if str.contains("iam") {
  //contains substring
}
else {
  //doesn't contain substring
}

C objetivo

NSString *stringData = @"Hello iam midhun";

if ([stringData containsString:@"iam"]) {
    //contains substring
}
else {
    //doesn't contain substring
}
Midhun p
fuente
-1
-(Bool)checkIf:(String)parentString containsSubstring:(String)checkString {
    NSRange textRange =[parentString rangeOfString:checkString];
    return textRange.location != NSNotFound // returns true if parent string contains substring else returns false
  }
iOS Nepal
fuente
1
En Objective-C tenemos el tipo 'NSString`. No tenemos Stringtipo. En segundo lugar, tenemos todos los objetos. Entonces, como argumento, debes pasar NSString. Voto por la eliminación debido a la mala calidad de una respuesta en una pregunta muy activa.
Aleksey Potapov
-2

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
pedrouan
fuente