Como verifico se uma string contém outra no Objective-C?

1212

Como posso verificar se uma string ( NSString) contém outra string menor?

Eu esperava algo como:

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

Mas o mais próximo que pude encontrar foi:

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

Enfim, essa é a melhor maneira de descobrir se uma string contém outra string?

Jonathan.
fonte
1
Eu gostaria de vê-lo adicionado também, mas, entretanto, é relativamente fácil adicioná-lo como uma categoria no NSString.
Isaac
2
Usando if ([string rangeOfString:@"hello"] == 0) {...}há um erro de incompatibilidade de tipo para NSRange e int. para corrigir isso, você deve alterar a linha para o seguinte:if ([string rangeOfString:@"hello"].length == 0) {...}
Neeku 11/11/13
1
iOS 8 acrescenta containsString: e aqui é uma maneira minimamente invasiva para adicionar iOS 7 suporte petersteinberger.com/blog/2014/...
Steve Moser
2
Sou desenvolvedor iOS desde o início e revisito constantemente este post para uma pasta de cópia rápida. Não consigo memorizar este. O stackoverflow mais visitado do meu histórico.
VaporwareWolf
basta usar Swift;)
Fattie

Respostas:

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

A chave é perceber que rangeOfString:retorna uma NSRangeestrutura e a documentação diz que ela retornará a estrutura {NSNotFound, 0}se o "palheiro" não contiver a "agulha".


E se você estiver no iOS 8 ou no OS X Yosemite, agora pode: (* NOTA: Isso travará seu aplicativo se esse código for chamado em um dispositivo iOS7).

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

(Também é assim que funcionaria no Swift)

👍

Dave DeLong
fonte
286
Para fazer uma pesquisa sem distinção entre maiúsculas e minúsculas, use "if ([string rangeOfString: @" bla "opções: NSCaseInsensitiveSearch] .location! = NSNotFound)"
Vanja
1
@ Dave DeLong Eu estava indo apenas para mencionar uma categoria que eu criei para esse fim antes de ler sua edição para a resposta! Desde que eu sou principalmente desenvolvedor ac #, fico feliz que eles adicionaram um método contains ao NSSTring.
precisa saber é o seguinte
Por que o compilador não diz nada se meu destino de implantação é o iOS7 e eu uso containsString?
Ricardo
3
E para aprofundar o argumento de @Vanja: se você usar o código de atalho [string containsString] que foi introduzido no iOS 8 / Yosemite, poderá usar o seguinte código para uma sequência que não diferencia maiúsculas de minúsculas: "[stringToSearch localizedCaseInsensitiveContainsString: string ] ", e este se você desejar fazer uma pesquisa sem distinção entre maiúsculas e minúsculas e diacrítico:" [stringToSearch localizedStandardContainsString: string] ".
Scott Kohlert 28/03
1
Observe que a expressão [string rangeOfString:@"bla"].location != NSNotFoundserá verdadeira quando string for nil!
funroll
158

Para iOS 8.0+ e macOS 10.10+, você pode usar o nativo do NSString containsString:.

Para versões mais antigas do iOS e macOS, você pode criar sua própria categoria (obsoleta) para o 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 o comentário de Daniel Galasko abaixo sobre nomeação

P i
fonte
13
+1 para obter um código resultante mais claro e reutilizável. Eu o transformei no liner único return [self rangeOfString:substring].location != NSNotFound;e o incluí na minha biblioteca de refatoração, es_ios_utils. github.com/peterdeweese/es_ios_utils
Peter DeWeese
4
Parece que a Apple gostou da sua ideia e adicionou esse recurso no iOS 8 e OSx 10.10 (Yosemite) como @DaveDeLong mencionado em sua resposta. +1
Islam Q.
7
A regra principal para as categorias obj-c é prefixar o nome do método com o prefixo do módulo de 3 letras. Este é o exemplo perfeito, pois agora entra em conflito com o iOS 7 e 10.10
Daniel Galasko
54

Como esse parece ser um resultado de alta classificação no Google, quero adicionar o seguinte:

O iOS 8 e o OS X 10.10 adicionam o containsString:método a NSString. Uma versão atualizada do exemplo de Dave DeLong para esses sistemas:

NSString *string = @"hello bla bla";
if ([string containsString:@"bla"]) {
    NSLog(@"string contains bla!");
} else {
    NSLog(@"string does not contain bla");
}
Lukas
fonte
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!");
}

// Como alternativa, você também pode usar o seguinte:

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

Com o iOS 8 e o Swift , podemos usar o localizedCaseInsensitiveContainsString método

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

 string.localizedCaseInsensitiveContainsString(substring) // true
Govind
fonte
1
Isso é bom. Não faço ideia por que eles não tinham esse método para o iOS 7
Lucas
@ Lucas, porque o Swift foi lançado com o iOS 8.0. mas com rápida você ainda pode suportar os dispositivos com iOS 7.
Hemang
13

Então, pessoalmente, eu realmente odeio, NSNotFoundmas entendo sua necessidade.

Mas algumas pessoas podem não entender as complexidades da comparação com o NSNotFound

Por exemplo, este código:

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

tem seus problemas:

1) Obviamente, se otherString = nileste código falhar. um teste simples seria:

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

resulta em !! BATIDA !!

2) O que não é tão óbvio para alguém novo no objetivo-c é que o mesmo código NÃO trava quando string = nil. Por exemplo, este código:

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

e este código:

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

ambos resultarão em

does string contains string - YES

O que claramente não é o que você deseja.

Portanto, a melhor solução que eu acredito que funciona é usar o fato de rangeOfString retornar o comprimento 0, então um código melhor e mais confiável é o seguinte:

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

OU SIMPLESMENTE:

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

que retornará para os casos 1 e 2

does string contains string - NO

Esses são meus 2 centavos ;-)

Verifique meu Gist para obter mais códigos úteis.

ucangetit
fonte
12

Uma versão aprimorada da solução de Pi , uma categoria no NSString, que não apenas informa se uma string é encontrada em outra string, mas também usa um intervalo por referência, é:

@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

Use-o 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
fonte
8

Aqui está um trecho de função de copiar e colar:

-(BOOL)Contains:(NSString *)StrSearchTerm on:(NSString *)StrText
{
    return [StrText rangeOfString:StrSearchTerm 
        options:NSCaseInsensitiveSearch].location != NSNotFound;
}
Durai Amuthan.H
fonte
Posso saber por que estou com voto negativo? É um trecho de código que funciona.
Durai Amuthan
6

Oneliner (menor quantidade de código. SECO, pois você possui apenas um NSLog):

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

tente isso,

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

Melhor solução. Tão simples como isso! Se você deseja encontrar uma palavra ou parte da string. Você pode usar esse código. Neste exemplo, vamos verificar se o valor da palavra contém "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
fonte
5

No Swift 4:

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

Se você precisar disso, escreva uma vez:

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
fonte
4

Em caso de rápida, isso pode ser usado

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

Se não se preocupe com a seqüência que diferencia maiúsculas de minúsculas. Tente isso uma vez.

NSString *string  = @"Hello World!";

if([string rangeOfString:@"hello" options:NSCaseInsensitiveSearch].location !=NSNotFound)
{
    NSLog(@"found");
}
else
{
    NSLog(@"not found");
}
Abhijit
fonte
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
fonte
1

Use a opção NSCaseInsensitiveSearch com rangeOfString: options:

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
}

Resultado da saída encontrado: Sim

As opções podem ser "or'ed" juntas e incluem:

NSCaseInsensitiveSearch NSLiteralSearch NSBackwardsSearch e mais

Nayab Muhammad
fonte
0

A primeira string contém ou não a segunda string,

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
fonte
0

Tente o seguinte:

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 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");
}
Amir.n3t
fonte
0

Swift 4 e acima

let str = "Hello iam midhun"

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

Objetivo-C

NSString *stringData = @"Hello iam midhun";

if ([stringData containsString:@"iam"]) {
    //contains substring
}
else {
    //doesn't contain substring
}
midhun p
fonte
-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
fonte
1
No Objective-C, temos o tipo 'NSString`. Nós não temos Stringtipo. Em segundo lugar, temos todos os objetos. Então, como argumento, você deve passar NSString. Eu voto pela exclusão devido à má qualidade de uma resposta sob uma pergunta altamente ativa.
Aleksey Potapov
-2

Se for necessária uma certa posição da string, esse código ocorrerá no Swift 3.0 :

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

let position = string.range(of: substring)?.lowerBound
pedrouan
fonte