objective-c cocoa nsstring

objective c - ¿Qué hace NSString''sLike: en realidad lo hace?



objective-c cocoa (2)

Estoy tratando de averiguar qué isLike: lo que isLike: realidad le hace a NSString s y tener problemas. La documentación de Apple es muy vaga:

Devuelve un valor booleano que indica si el receptor es "similar" a otro objeto dado.

...

La implementación predeterminada para este método proporcionada por el método NSObject devuelve NO . NSString también proporciona una implementación de este método, que devuelve YES si el receptor coincide con un patrón descrito por objeto.

Menciona un "patrón", pero con algunas pruebas rudimentarias, no parece estar usando expresiones regulares. ¿Cuál es exactamente el formato del patrón en este caso?


Como otros han publicado, la documentación de Apple no describe el comportamiento de [NSString isLike:] en detalle como se ve here :

La implementación predeterminada para este método proporcionada por el método NSObject devuelve NO. NSString también proporciona una implementación de este método, que devuelve SÍ si el receptor coincide con un patrón descrito por objeto.

Como otros sugirieron, puede estar basado en NSPredicate . Si es así, es probable que utilice NSComparisonPredicate con el tipo de operador NSLikePredicateOperatorType como se describe here :

NSMatchesPredicateOperatorType

Una expresión regular completa que coincide con el predicado.

Disponible en OS X v10.4 y posteriores.

NSLikePredicateOperatorType

Un subconjunto simple del predicado MATCHES, similar en comportamiento a SQL LIKE.

Disponible en OS X v10.4 y posteriores.

Aunque la funcionalidad puede ser un simple subconjunto de expresiones regulares, la sintaxis es definitivamente diferente. Probé lo siguiente localmente en OS X 10.10.5 Hoy:

- (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"]; }

Y este código produce estos resultados:

[@"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

¿Así es isLike: parece que le isLike: apoyar ? y * como el archivo globbing con barra invertida / para escapar de la interpretación especial. También admite clases de caracteres con [ y ] con rangos definidos con - . Barra invertida para escapar de la apertura [ , y barra invertida para escapar ] y - dentro de la clase.


El encabezado NSScriptWhoseTest.h proporciona un poco más de información:

@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