3

predicateWithFormat:我对 NSPredicate 的方法有一个(对我来说)奇怪的案例。

使用以下内容,我将两个 NSPredicate 实例的描述记录到控制台:

NSNumber *myNumber = [NSNumber numberWithInt:1];

NSString *predicateFormatByHand = [NSString stringWithFormat:@"self MATCHES 'chp%@_img[0-9]+\\.png'", myNumber];
NSPredicate *firstPredicate = [NSPredicate predicateWithFormat:predicateFormatByHand];

NSLog(@"firstPredicate description: %@", firstPredicate);

NSPredicate *secondPredicate = [NSPredicate predicateWithFormat:@"self MATCHES 'chp%@_img[0-9]+\\.png'", myNumber];

NSLog(@"secondPredicate description: %@", secondPredicate);

这输出:

 firstPredicate description: SELF MATCHES "chp1_img[0-9]+.png"
secondPredicate description: SELF MATCHES "chp%@_img[0-9]+.png"

我希望这些描述是相同的。

有人可以解释为什么他们不是吗?

(在这个问题之后,我已经为嵌入式单引号使用了各种转义序列,但是这样做时,NSPredicate 一直抱怨它无法解析格式字符串。我很高兴知道发生了什么。)

更新:一个答案表明使用 NSNumber 而不是 int 是一个问题,所以:

NSPredicate *thirdPredicate = [NSPredicate predicateWithFormat:@"self MATCHES 'chp%d_img[0-9]+\\.png'", [myNumber intValue]];

NSLog(@"thirdPredicate description: %@", thirdPredicate);   

我最初是从这个开始的,但是输出是一样的:

thirdPredicate description: SELF MATCHES "chp%d_img[0-9]+.png"

(这意味着不评估格式说明符。)

4

3 回答 3

4

答案很简单: 使用的解析器NSPredicate假定引号内的任何内容都是字符串文字,并且不会尝试对其内容进行任何替换。如果您需要一个动态字符串值,则必须先构建字符串,然后再将其替换为谓词格式字符串,如您的第一个示例所示。

于 2012-08-19T12:57:41.177 回答
2

......因为predicate不是这样的事情string

对于任何predicates,您应该只使用两个格式说明符 100% 安全:

  • 一个用于%K);和
  • 一个用于( %@);

添加到predicate. 这就是为什么您的第二个(和第三个)predicates没有在值内格式化的原因。

您可以在将其添加到类似之前格式化该值: predicate

NSNumber *myNumber = [NSNumber numberWithInt:1];
NSString *string = [NSString stringWithFormat:@"chp%@_img[0-9]+\\.png", myNumber];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", string];
NSLog(@"%@", predicate);

结果是:

SELF MATCHES "chp1_img[0-9]+\\.png"

...永远不要忘记我的第一句话:thepredicates和 thestrings不是一回事。

于 2012-08-19T12:31:49.407 回答
0

我的解释

%@ 是对象值的 var arg 替换

在“谓词编程指南”中,%@它只能用于替换核心数据对象可以与之比较的值。例如

NSNumber *myNumber = [NSNumber numberWithInt:1]; 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"count = %@", myNumber];

如果“count”是实体的 Number 属性,则完全有效。它类似于将值绑定到 SQLite 准备好的语句。

如果%@可以用于谓词中的一般字符串格式化,那么就不需要有两个不同的格式说明符%K 以及%@键路径和值。

于 2012-08-19T11:44:16.187 回答