This question already has an answer here:
-
Warning: “format not a string literal and no format arguments”
11 answers
I am getting "Format string is not string literal" warning from following line
NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:valist];
I using this in following function
- (void)logMessage:(NSString *)format
level:(LoggingLevel)level
withParameters:(va_list)valist {
if (level >= self.loggingLevel) {
NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:valist];
}
Any idea how to fix this ? I am using Xcode 4.6.3
If you tell the compiler that your method has a format-like argument, using the
NS_FORMAT_FUNCTION
macro:
- (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];
}
}
then
- the compiler warning in your method goes away, but
- you get a warning if you call your method with a format string which is not a string literal.
Example:
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: The same applies to the functions mentioned in your comments.
They should also be "tagged" with 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];
}
Suppress it using:
#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
The format string should be @"something with some format specifiers to be replaced by the varargs" just like in stringWithFormat: or in NSLog
Remember that @ has a special meaning everywhere in Objective-C. It is a sigil indicating a compiler directive. The compiler will know what to do with the following token ( expanding it or converting contents, sometimes looking for a matching paired directive like @end
It may be the right solutio for you just to suppress the warning, as @trojanfoe suggests. It is just that the warning is there for a reason.
In the event that your format string does not match the number and/or type of your arguments, you application may break on runtime. When you provide the format as string literal such as @"My output is: %@" ... then you enable the compiler to check upon types and numer of arguments.
There may be good reasons for using a string varaible as format. However, in that case you are on your own when it comes to avoiding this type of error.
Anyway, I'd suggest re-thinking your algorithm in favor of using string literals.