2016-03-09 21 views
23

Sto cercando di capire cosa fa effettivamente isLike: a NSString s e di avere problemi. Apple own documentation è molto vaga:Che cos'è NSString's isLike: effettivamente?

restituisce un valore booleano che indica se il ricevitore è "come" un altro dato oggetto.

...

L'implementazione predefinita di questo metodo fornito da NSObject metodo ritorna NO. NSString fornisce anche un'implementazione di questo metodo, che restituisce YES se il ricevitore corrisponde a un modello descritto dall'oggetto .

Si parla di "modello", ma con alcuni test rudimentali, non sembra che stia usando espressioni regolari. Qual è esattamente il formato del pattern in questo caso?

+2

Corrisponde al comportamento di [l'operatore 'LIKE' di' NSPredicate'] (https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html # // apple_ref/doc/uid/TP40001795-215868)? –

+0

@JoshCaswell '*' funziona come descritto qui, ma esegue anche il confronto delle sottostringhe in una certa misura ... quindi "FooBar" isLike "Foo" – Earlz

+1

@Earlz, ho provato '[@" FooBar "isLike: @" Foo "] 'ma ha ottenuto un risultato falso. – cdlane

risposta

10

Come altri hanno scritto, la documentazione di Apple non descrive il comportamento di [NSString isLike:] in dettaglio come si è visto here:

L'implementazione di default per questo metodo fornito dal metodo NSObject restituisce NO. NSString fornisce anche un'implementazione di questo metodo, che restituisce SÌ se il ricevitore corrisponde a un modello descritto da un oggetto.

Come altri suggerito potrebbe essere basato su NSPredicate. Se così è probabile utilizzando NSComparisonPredicate con operatore tipo NSLikePredicateOperatorType come descritto here:

NSMatchesPredicateOperatorType

Una piena espressione regolare che corrisponde predicato.

Disponibile in OS X v10.4 e versioni successive.

NSLikePredicateOperatorType

Un semplice sottoinsieme delle partite predicato, un comportamento simile a SQL SIMILE.

Disponibile in OS X v10.4 e versioni successive.

Sebbene la funzionalità possa essere un semplice sottoinsieme di espressioni regolari, la sintassi è decisamente diversa. Ho testato quanto segue a livello locale su OS X 10.10.5 Oggi:

- (NSString *)escapeString:(NSString *)value { 
    return [value stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; 
} 

- (void)is:(NSString *)value like:(NSString *)pattern note:(NSString *)note { 
    NSLog(@"[@\"%@\" isLike:@\"%@\"] == %@ // %@", 
      [self escapeString:value], 
      [self escapeString:pattern], 
      ([value isLike:pattern] ? @"true" : @"false"), 
      note); 
} 

- (void)testAll { 
    // each note contains result on OS X 10.10.5 on 20160503 
    [self is:@"foo" like:@"f*" note:@"true, '*' wildcard works like file globbing, not RE"]; 
    [self is:@"foo" like:@"foo*" note:@"true, '*' is zero or more"]; 
    [self is:@"foo" like:@"f?o" note:@"true, '?' wildcard works like file globbing, not RE"]; 
    [self is:@"foo" like:@"f?" note:@"false, not more then one"]; 
    [self is:@"foo" like:@"f?oo" note:@"false, not less than one"]; 
    [self is:@"foo" like:@"Foo" note:@"false, is case-sensitive (also see isCaseInsensitiveLike:)"]; 
    [self is:@"foo" like:@"[Ff]oo" note:@"true, supports character classes"]; 
    [self is:@"foo" like:@"[^F]oo" note:@"false, does not support RE negation in character classes"]; 
    [self is:@"foo" like:@"[a-z]oo" note:@"true, supports ranges"]; 
    [self is:@"foo" like:@"[[:lower:]]oo" note:@"false, does not support POSIX named classes"]; 
    [self is:@"]oo" like:@"[]]oo" note:@"false, does not support ']' as first character in a class"]; 
    [self is:@"]oo" like:@"[\\]]oo" note:@"true, backslash to escape interpretation of ']' as end of class"]; 
    [self is:@"[oo" like:@"\\[oo" note:@"true, backslash to escape interpretation as start of class"]; 
    [self is:@"-oo" like:@"[x\\-z]oo" note:@"true, supports escape of '-' in character classes"]; 
    [self is:@"?oo" like:@"\\?oo" note:@"true, escape with backslash"]; 
    [self is:@"foo" like:@"\\?oo" note:@"false, this is not just wildcard matching"]; 
    [self is:@"*oo" like:@"\\*oo" note:@"true, escape with backslash"]; 
    [self is:@"foo" like:@"\\*oo" note:@"false, this is not just wildcard matching"]; 
    [self is:@"\\foo" like:@"\\\\*oo" note:@"true, escape backslash with another backslash"]; 
} 

E questo codice produce questi risultati:

[@"foo" isLike:@"f*"] == true // true, '*' wildcard works like file globbing, not RE 
[@"foo" isLike:@"foo*"] == true // true, '*' is zero or more 
[@"foo" isLike:@"f?o"] == true // true, '?' wildcard works like file globbing, not RE 
[@"foo" isLike:@"f?"] == false // false, not more then one 
[@"foo" isLike:@"f?oo"] == false // false, not less than one 
[@"foo" isLike:@"Foo"] == false // false, is case-sensitive (also see isCaseInsensitiveLike:) 
[@"foo" isLike:@"[Ff]oo"] == true // true, supports character classes 
[@"foo" isLike:@"[^F]oo"] == false // false, does not support RE negation in character classes 
[@"foo" isLike:@"[a-z]oo"] == true // true, supports ranges 
[@"foo" isLike:@"[[:lower:]]oo"] == false // false, does not support POSIX named classes 
[@"]oo" isLike:@"[]]oo"] == false // false, does not support ']' as first character in a class 
[@"]oo" isLike:@"[\\]]oo"] == true // true, backslash to escape interpretation of ']' as end of class 
[@"[oo" isLike:@"\\[oo"] == true // true, backslash to escape interpretation as start of class 
[@"-oo" isLike:@"[x\\-z]oo"] == true // true, supports escape of '-' in character classes 
[@"?oo" isLike:@"\\?oo"] == true // true, escape with backslash 
[@"foo" isLike:@"\\?oo"] == false // false, this is not just wildcard matching 
[@"*oo" isLike:@"\\*oo"] == true // true, escape with backslash 
[@"foo" isLike:@"\\*oo"] == false // false, this is not just wildcard matching 
[@"\\foo" isLike:@"\\\\*oo"] == true // true, escape backslash with another backslash 

Così isLike: sembra sostenere ? e * come file di globbing con backslash \ per sfuggire interpretazione speciale. Supporta anche classi di caratteri con [ e ] con intervalli definiti con -. Barra rovesciata per uscire dall'apertura [ e backslash per uscire ] e - all'interno della classe.

8

L'intestazione NSScriptWhoseTest.h fornisce qualche informazione in più:

@interface NSObject (NSComparisonMethods) 
... 

- (BOOL)isLike:(NSString *)object; 
    // argument should be a string using simple shell wildcards (* and ?). 
    // (e.g. "Stev*" or "N?XT"). 
    // Returns NO if receiver is not an NSString. 

- (BOOL)isCaseInsensitiveLike:(NSString *)object; 

@end 
+1

Insieme al collegamento @JoshCaswell a [NSPredicate] (https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html#//apple_ref/doc/uid/TP40001795-215868), è probabile che '*' e '?' sono gli unici personaggi del modello. Si noti che '\' è permesso anche per l'escape: '[@" F? Oo "isLike: @" \\ F \\? Oo "]' è 'true' –

+0

Ho scoperto che dopo qualche tempo questo è grossolanamente incompleto. Permette anche classi di caratteri, cioè 'isLike:" [abc] foobar "' restituirà true per "afoobar" e "cfoobar" – Earlz

Problemi correlati