警告:格式字符串不是字符串文字

时间:2013-06-26 13:58:26

标签: ios objective-c clang

我从以下行获取“格式字符串不是字符串文字”警告

NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:valist];

我在以下功能中使用它

- (void)logMessage:(NSString *)format
         level:(LoggingLevel)level
withParameters:(va_list)valist {
         if (level >= self.loggingLevel) {
              NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:valist];        
         } 

知道怎么解决这个问题吗?我正在使用Xcode 4.6.3

4 个答案:

答案 0 :(得分:10)

使用以下方法取消它:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-nonliteral"

- (void)logMessage:(NSString *)format
         level:(LoggingLevel)level
withParameters:(va_list)valist {
         if (level >= self.loggingLevel) {
              NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:valist];        
         } 

#pragma clang diagnostic pop

答案 1 :(得分:10)

如果你告诉编译器你的方法有类似格式的参数,请使用 NS_FORMAT_FUNCTION宏:

- (void)logMessage:(NSString *)format
         level:(LoggingLevel)level
withParameters:(va_list)valist NS_FORMAT_FUNCTION(1,0) {
         if (level >= self.loggingLevel) {
              NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:valist];        
         } 
}

然后

  • 您方法中的编译器警告消失,
  • 如果使用不是字符串文字的格式字符串调用方法,则会收到警告。

示例:

NSString *abc = @"foo %@ bar";
[self logMessage:abc level:7 withParameters:NULL];

warning: format string is not a string literal [-Wformat-nonliteral]
[self logMessage:abc level:7 withParameters:NULL];
                 ^~~

已添加:这同样适用于评论中提到的功能。 它们也应该使用NS_FORMAT_FUNCTION“标记”:

+ (void)logVeryFineWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2)
{
    va_list ap;
    va_start(ap, format);
    [[self sharedInstance] logMessage:format level:VERY_FINE withParameters:ap];
    va_end(ap);
}

+ (void)say:(NSString *)formatstring, ... NS_FORMAT_FUNCTION(1,2)
{
    va_list arglist;
    va_start(arglist, formatstring);
    // This is not needed: 
    // NSString *litralString = [NSString stringWithFormat:@"%@",formatstring];
    NSString *statement = [[NSString alloc] initWithFormat:formatstring arguments:arglist];
    va_end(arglist);
    [ModalAlert ask:statement withCancel:@"Okay" withButtons:nil];
}

答案 2 :(得分:0)

格式字符串应该是@“某些格式说明符要被varargs替换”,就像在stringWithFormat中一样:或在NSLog中

请记住@在Objective-C中到处都有特殊含义。它是一个指示编译器指令的符号。编译器将知道如何处理以下令牌(扩展它或转换内容,有时寻找匹配的配对指令,如@end

答案 3 :(得分:-1)

正如@trojanfoe建议的那样,对你来说,抑制警告可能是正确的解决办法。只是警告是有原因的。

如果您的格式字符串与参数的数量和/或类型不匹配,则应用程序可能会在运行时中断。当您将格式提供为字符串文字,例如@“我的输出是:%@”时,您可以使编译器检查参数的类型和数量。

使用字符串变量作为格式可能有充分的理由。但是,在这种情况下,当涉及到避免此类错误时,您就可以独立完成。

无论如何,我建议重新考虑你的算法,而不是使用字符串文字。

相关问题