predicateWithFormat vs stringWithFormat:前者应该和后者做同样的事吗?

时间:2011-08-30 04:17:38

标签: cocoa macos nsarray nspredicate

我有一个带有文件名的数组,我想找到以...结尾的所有名称当traceNum为1时, 00001.trc 我尝试了这个:

NSPredicate *tracePredicate = [NSPredicate predicateWithFormat:@"SELF ENDSWITH \"%05d.trc\"", traceNum];

我的谓词是SELF ENDSWITH "%05d.trc"而不是SELF ENDSWITH "00001.trc"

我试过了:

NSPredicate *tracePredicate = [NSPredicate predicateWithFormat:@"SELF ENDSWITH %@%05d.trc%@", @"\"", traceNum, @"\""];

我得到了一个例外:Unable to parse the format string "SELF ENDSWITH %@%05d.trc%@"

所以我尝试了这个:

NSPredicate *tracePredicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"SELF ENDSWITH \"%05d.trc\"", traceNum]];

它有效。

除了stringWithFormat之外,我真的需要predicateWithFormat,还是我在创建谓词时没有做到正确的事情?

1 个答案:

答案 0 :(得分:5)

你是对的; predicateWithFormat:stringWithFormat:不完全相同。

由于几个主要原因,情况有所不同:

  1. 实际上并没有创建新字符串。它只是查看格式字符串并查看下一个要替换的内容,将其从va_list弹出,并将其装入适当的NSExpression对象。
  2. 必须支持NSString不支持的格式说明符:%K。这是您在关键路径中替换的方式。如果您尝试使用%@替换属性的名称,它实际上将被解释为文字字符串,而不是属性名称。
  3. 不支持使用格式限制(我不确定适当的术语是什么),例如05中的%05d。首先,它没有意义。 NSPredicate进行数值比较(在这种情况下000055是相同的,因此零填充是无关紧要的)和字符串比较(在此之前你可以自己格式化字符串把它交给NSPredicate)。 (它进行了其他比较,比如收集操作,但我现在正在跳过那些)
  4. 那么,你怎么做你想做的事情?最好的方法是:

    NSString *trace = [NSString stringWithFormat:@"%05d.trc", traceNum];
    NSPredicate *p = [NSPredicate predicateWithFormat:@"SELF ENDSWITH %@", trace];
    

    这样您可以执行所需的所有格式设置,但仍然使用更正确的方法将常量字符串作为谓词格式传递。