Come posso verificare se una stringa contiene un'altra stringa in Objective-C?


1212

Come posso verificare se una stringa ( NSString) contiene un'altra stringa più piccola?

Speravo in qualcosa del tipo:

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

Ma il più vicino che potessi trovare era:

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

Ad ogni modo, è il modo migliore per scoprire se una stringa contiene un'altra stringa?


1
Mi piacerebbe vederlo anche aggiunto, ma nel frattempo è relativamente facile aggiungerlo come categoria su NSString.
Isaac,

2
L'uso if ([string rangeOfString:@"hello"] == 0) {...}di un errore di mancata corrispondenza del tipo per NSRange e int. per risolvere il problema, dovresti cambiare la riga come segue:if ([string rangeOfString:@"hello"].length == 0) {...}
Neeku,

1
iOS 8 aggiunge contieneString: ed ecco un modo minimamente invasivo per aggiungere il supporto per iOS 7 petersteinberger.com/blog/2014/…
Steve Moser

2
Sono stato uno sviluppatore iOS sin dall'inizio e rivisito costantemente questo post per un rapido copia incolla. Non riesco a memorizzare questo. Post stackoverflow più visitato nella mia cronologia.
VaporwareWolf

usa Swift;)
Fattie il

Risposte:


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

La chiave sta notando che rangeOfString:restituisce una NSRangestruttura e la documentazione afferma che restituisce la struttura {NSNotFound, 0}se il "pagliaio" non contiene "ago".


E se utilizzi Yosemite per iOS 8 o OS X, ora puoi fare: (* NOTA: questo bloccherà la tua app se questo codice viene chiamato su un dispositivo iOS7).

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

(Questo è anche il modo in cui funzionerebbe in Swift)

👍


286
Per effettuare una ricerca senza distinzione tra maiuscole e minuscole, utilizzare "if ([string rangeOfString: @" bla "opzioni: NSCaseInsensitiveSearch] .location! = NSNotFound)"
Vanja

1
@Dave DeLong Stavo per menzionare una categoria che ho creato a questo scopo prima di leggere la tua modifica alla risposta! Dato che sono principalmente sviluppatore di ac #, sono lieto che abbiano aggiunto un metodo contiene a NSSTring.
dherrin79,

Perché il compilatore non dice nulla se il mio target di distribuzione è iOS7 e utilizzo contengaString?
Ricardo,

3
E per approfondire il punto sollevato da @Vanja: se si intende utilizzare il codice di scelta rapida [stringrenString] che è stato introdotto in iOS 8 / Yosemite, è possibile utilizzare il seguente codice per una stringa senza distinzione tra maiuscole e minuscole: "[stringToSearch localizedCaseInsensitiveConInsensitiveContainsString: string ] ", e questo se vuoi fare un caso e una ricerca insensibile ai segni diacritici:" [stringToSearch localizedStandardContainsString: string] ".
Scott Kohlert,

1
Nota che l'espressione [string rangeOfString:@"bla"].location != NSNotFoundsarà vera quando stringa è nil!
funroll,

158

Per iOS 8.0+ e macOS 10.10+, puoi usare il nativo di NSString containsString:.

Per le versioni precedenti di iOS e macOS, puoi creare la tua categoria (obsoleta) per 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: osservare il commento di Daniel Galasko di seguito in merito alla denominazione


13
+1 per un codice risultante più chiaro e riutilizzabilità. L'ho trasformato nell'unico liner return [self rangeOfString:substring].location != NSNotFound;e l'ho incluso nella mia libreria di refactoring, es_ios_utils. github.com/peterdeweese/es_ios_utils
Peter DeWeese

4
Sembra che ad Apple piaccia la tua idea e abbia aggiunto questa funzione in iOS 8 e OSx 10.10 (Yosemite), come indicato da @DaveDeLong nella sua risposta. +1
Islam Q.

7
La regola cardinale per le categorie obj-c è quella di anteporre il nome del metodo con il prefisso del modulo di 3 lettere. Questo è l'esempio perfetto poiché ora è in conflitto con iOS 7 e 10.10
Daniel Galasko,

54

Poiché questo sembra essere un risultato di alto livello in Google, voglio aggiungere questo:

iOS 8 e OS X 10.10 aggiungono il containsString:metodo a NSString. Una versione aggiornata dell'esempio di Dave DeLong per quei sistemi:

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

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!");
}

// In alternativa puoi usare anche quanto segue:

if (rangeValue.location == NSNotFound) 
{
    NSLog(@"string does not contain hello");
} 
else 
{
    NSLog(@"string contains hello!");
}

22

Con iOS 8 e Swift , possiamo usare il localizedCaseInsensitiveContainsString metodo

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

 string.localizedCaseInsensitiveContainsString(substring) // true

1
Questo è buono. Non ho idea del perché non avessero questo metodo per iOS 7
Lucas,

@Lucas, perché Swift è stato lanciato con iOS 8.0. ma con swift puoi ancora supportare i dispositivi con iOS 7.
Hemang

13

Quindi personalmente odio davvero NSNotFoundma capisco la sua necessità.

Ma alcune persone potrebbero non comprendere la complessità del confronto con NSNotFound

Ad esempio, questo codice:

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

ha i suoi problemi:

1) Ovviamente se otherString = nilquesto codice andrà in crash. un semplice test sarebbe:

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

risultati in !! CRASH !!

2) Ciò che non è così ovvio per qualcuno che non conosce Object-C è che lo stesso codice NON si bloccherà quando string = nil. Ad esempio, questo codice:

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

e questo codice:

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

comporterà entrambi

does string contains string - YES

Che chiaramente NON è quello che vuoi.

Quindi la soluzione migliore che credo funzioni è usare il fatto che rangeOfString restituisce la lunghezza di 0, quindi un codice migliore e più affidabile è questo:

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

O SEMPLICEMENTE:

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

che verrà restituito per i casi 1 e 2

does string contains string - NO

Sono i miei 2 centesimi ;-)

Controlla il mio Gist per un codice più utile.


12

Una versione migliorata della soluzione di P i , una categoria su NSString, che non solo dirà, se una stringa viene trovata all'interno di un'altra stringa, ma prende anche un intervallo per riferimento, è:

@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

Usalo come:

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

8

Ecco uno snippet di funzione copia e incolla:

-(BOOL)Contains:(NSString *)StrSearchTerm on:(NSString *)StrText
{
    return [StrText rangeOfString:StrSearchTerm 
        options:NSCaseInsensitiveSearch].location != NSNotFound;
}

Posso sapere perché sono stato sottoposto a downgrade? È uno snippet di codice funzionante
Durai Amuthan,

6

Oneliner (minore quantità di codice. ASCIUTTO, poiché ne hai solo uno NSLog):

NSString *string = @"hello bla bla";
NSLog(@"String %@", ([string rangeOfString:@"bla"].location == NSNotFound) ? @"not found" : @"cotains bla"); 

6
NSString *categoryString = @"Holiday Event";
if([categoryString rangeOfString:@"Holiday"].location == NSNotFound)
{
    //categoryString does not contains Holiday
}
else
{
    //categoryString contains Holiday
}

5

prova questo,

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

5

Soluzione migliore. Semplice come questo! Se vuoi trovare una parola o parte della stringa. Puoi usare questo codice. In questo esempio verificheremo se il valore di 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");
}

5

In Swift 4:

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

4

Se ne hai bisogno una volta scrivi:

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;

4

In caso di rapidità, questo può essere usato

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

2

Se non preoccuparti della stringa con distinzione tra maiuscole e minuscole. Prova una volta.

NSString *string  = @"Hello World!";

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

1

Si prega di utilizzare questo codice

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

1

Utilizzare l'opzione NSCaseInsensitiveSearch con rangeOfString: opzioni:

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
}

Il risultato dell'output è stato trovato: Sì

Le opzioni possono essere "o" usate insieme e includono:

NSCaseInsensitiveSearch NSLiteralSearch NSBackwardsSearch e altro


0

La prima stringa contiene o meno la seconda stringa,

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

if (range.length > 0) {
    NSLog(@"Detected");
}
else {
    NSLog(@"Not detected");
}

0

Prova questo:

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");
}

Per Objective-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");
}

0

Swift 4 e sopra

let str = "Hello iam midhun"

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

Objective-C

NSString *stringData = @"Hello iam midhun";

if ([stringData containsString:@"iam"]) {
    //contains substring
}
else {
    //doesn't contain substring
}

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

1
In Objective-C abbiamo il tipo 'NSString`. Non abbiamo Stringtipo. In secondo luogo, abbiamo tutti gli oggetti. Quindi, come argomento, dovresti passare NSString. Voto per la cancellazione a causa della scarsa qualità di una risposta con una domanda molto attiva.
Aleksey Potapov,

-2

Se è necessaria una determinata posizione della stringa, questo codice viene inserito in Swift 3.0 :

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

let position = string.range(of: substring)?.lowerBound
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.