警告:格式string不是一个string文字

我得到“格式string不是string文字”警告从下面的行

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

如果你告诉编译器你的方法有一个类似于格式的参数,使用NS_FORMAT_FUNCTIONmacros:

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

然后

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

例:

 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]; ^~~ 

ADDED:同样适用于您评论中提到的function。 他们也应该用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]; } 

用下面的方法压制它:

 #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 

格式string应该是@“某些格式说明符要被可变参数replace”,就像在stringWithFormat中:或NSLog

请记住,在Objective-C中,@具有特殊的含义。 这是一个表示编译器指令的签名。 编译器将知道如何处理以下标记(扩展或转换内容,有时候会寻找匹配的配对指令,例如@end

正如@trojanfoe所build议的那样,这可能是正确的解决scheme,只是为了压制警告。 只是警告是有原因的。

如果您的格式string与您的参数的数量和/或types不匹配,您的应用程序可能会在运行时中断。 当你提供格式为string文字,比如@“My output is:%@”…那么你可以让编译器检查参数的types和数量。

使用stringvariables作为格式可能有很好的理由。 但是,在这种情况下,您应该避免这种types的错误。

无论如何,我build议重新思考你的algorithm,而不是使用string文字。