2014-10-16 28 views
70

Sto provando a filtrare un array in base a uno dei suoi campi stringa.NSString containsString si arresta in modo anomalo

Sia nameLower e filterLower ha valore NSString dentro, eppure continuo a ricevere:

__NSCFString containsString:]: unrecognized selector sent to instance 0x7f876b79e160 

-(void) filterFriendsArray:(NSString*)filter { 
    [_filteredFriendsArray removeAllObjects]; 
    for (FacebookUser* user in _friendsArray) 
    { 
     NSString* nameLower = [user.user.name lowercaseString]; 
     NSString* filterLower = [filter lowercaseString]; 
     if ([nameLower containsString:filterLower]) 
      [_filteredFriendsArray addObject:user]; 
    } 
    _displayedFriendsArray = _filteredFriendsArray; 
} 
+46

Stai utilizzando un iOS inferiore a 8? Il metodo 'containsString:' è stato aggiunto solo in iOS 8. –

+6

È curioso che 'containsString:' non sia documentato online. –

+0

@IanMacDonald hai ragione .. postalo come risposta in modo da poterlo accettare .. –

risposta

118

Se si desidera che il codice per lavorare su iOS 7 e iOS 8 si dovrebbe usare uno dei rangeOfString chiede invece . Fondamentalmente se l'intervallo restituito ha una lunghezza pari a zero, la sottostringa non è lì.

/* These methods return length==0 if the target string is not found. So, to check for containment: ([str rangeOfString:@"target"].length > 0). Note that the length of the range returned by these methods might be different than the length of the target string, due composed characters and such. 
*/ 
- (NSRange)rangeOfString:(NSString *)aString; 
- (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask; 
- (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask range:(NSRange)searchRange; 
- (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask range:(NSRange)searchRange locale:(NSLocale *)locale NS_AVAILABLE(10_5, 2_0); 

Ovviamente è banale da implementare containsString te stesso in una categoria utilizzando rangeOfString:

@implementation NSString (Contains) 

- (BOOL)myContainsString:(NSString*)other { 
    NSRange range = [self rangeOfString:other]; 
    return range.length != 0; 
} 

@end 
+0

su osx rangeOfString sembra restituire nil e non 0 se la stringa non è contenuta –

+2

// "su osx rangeOfString sembra restituire nil e non 0 se la stringa non è contenuta" L'ultima volta che ho controllato, nil era uguale a zero. – w0mbat

+5

sarebbe bello vedere questo problema al momento della compilazione – user230910

7

confrontare rangeOfString con NSNotFound

NSRange range = [self rangeOfString:other]; 
if(range.location != NSNotFound){ 
    //do something 
} 
-1

versione Swift della risposta data dal w0mbat:

+0

L'intervallo non ha una lunghezza membro. – lostintranslation

+0

Modificata la mia risposta, a quanto pare String's Range non contiene "length", ma NSString lo fa. –

3

Uso seguente:

if (![[NSString class] respondsToSelector:@selector(containsString)]) 
    { 
     //ios 7 
     NSRange range = [mystring rangeOfString:other]; 
     if(range.location != NSNotFound){ 
      //do something 
     } 
    } 
    else //for iOS 8 
    { 
      if ([mystring containsString: other]) 
      { 
       //do something 
      }        
    } 
0

Per coloro che ha incontrato questo XLForm, assicurarsi che quando si installa XLForm utilizzando baccelli

platform :ios, '7' 
pod 'XLForm' 

Si è già fissato in 3.1

da

if ([cellClassString contains:@"/"]) { 

} 

a

if ([cellClassString rangeOfString:@"/"].location != NSNotFound) { 

} 
0

ho incapsulare la mia soluzione in YJKit, e si può chiamare - [NSString containsString:] anche per vecchia versione che sotto iOS 8.

bool _yj_streq(const char *str1, const char *str2, size_t length) { 
    for (int i = 0; i < length; i++) { 
     if (*str1++ != *str2++) { 
      return false; 
     } 
    } 
    return true; 
} 

- (BOOL)yj_containsString:(NSString *)string { 

    NSAssert(string != nil, @"*** -[%@ containsString:] can not use nil argument.", [self class]); 

    size_t len1 = (size_t)self.length; 
    size_t len2 = (size_t)string.length; 

    if (len1 == 0 || len2 == 0 || len1 < len2) { 
     return NO; 
    } 

    const char *str1 = self.UTF8String; 
    const char *str2 = string.UTF8String; 

    for (size_t i = 0; i <= len1 - len2; i++) { 
     const char *substr1 = str1 + i; 
     if (_yj_streq(substr1, str2, len2)) { 
      return YES; 
     } else { 
      continue; 
     } 
    } 

    return NO; 
} 

Ecco il mio codice sorgente: https://github.com/huang-kun/YJKit/blob/master/YJKit/Base/Foundation/Categories/Generics/NSString%2BYJCompatible.m

+1

Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il link per riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. – Marusyk

Problemi correlati