2013-06-26 135 views
4

我得到“格式字符串不是字符串常量”,在下面的函数从以下行警告:格式字符串不是一个字符串文字

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

回答

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]; 
} 
+1

+1比我的回答更好 – trojanfoe

+0

@trojanfoe:谢谢! –

+0

@MartinR是删除了警告,但正如你上面说的,我在\t [[self sharedInstance] logMessage:format level:FINE withParameters:ap]上得到警告; – AAV

0

格式字符串应该是@“一些与由可变参数来代替一些格式说明”就像在stringWithFormat:或的NSLog

记住,@到处都有特殊的含义在Objective-C中。它是一个表示编译器指令的印记。编译器会知道该怎么做了以下令牌(扩大,或转换内容,有时找一个匹配的配对指令像@end

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 
+0

不错的魔术答案 – uchuugaka

-1

这可能是正确的搜索解决方案为您刚刚取消此警告,如@trojanfoe建议。这只是警告是有原因的。

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

可能有很好的理由使用字符串变量作为格式。但是,在这种情况下,您应该避免这种类型的错误。

无论如何,我会建议重新考虑你的算法,以支持使用字符串文字。

+0

我不同意;我认为@ MartinR的答案效果最好。 – trojanfoe

相关问题