I found something strange when trying to use width specifiers with %@
. They work fine in NSLog
but not with NSString stringWithFormat:
.
Example:
NSString *rightAligned = @"foo";
NSString *leftAligned = @"1";
NSLog(@"| %15@ | %-15@ |", rightAligned, leftAligned);
And you get the expected output of:
| foo | 1 |
But replace the NSLog
with stringWithFormat:
:
NSString *test = [NSString stringWithFormat:@"| %15@ | %-15@ |", rightAligned, leftAligned];
And the value of test
is incorrectly:
| foo | 1 |
If I change this to use %s
and cStringUsingEncoding:
then it works:
NSString *test2 = [NSString stringWithFormat:@"| %15s | %-15s |", [rightAligned cStringUsingEncoding:NSUTF8StringEncoding], [leftAligned cStringUsingEncoding:NSUTF8StringEncoding]];
The result is the same as with NSLog
.
What makes this really strange is that NSLog
is basically just a wrapper around NSString stringWithFormat:
.
So why the different results? Why aren't format specifiers honored for %@
in stringWithFormat
but they are with NSLog
?
As a side note, the Swift String init(format:)
initializer has the same problem with %@
and width specifiers.
The mystery is why %15@
would ever work. It should not.
Format specifiers come from sprintf
which has no %@
(it is just a special extension for Objective-C). As far as stringWithFormat
goes, %15s
has always been the way to say this; I can cite Stack Overflow examples such as NSString stringwithformat: Padding 2 strings with unknown length.
I'm guessing it only "works" because it now uses os_log
under the hood; unfortunately, the os_log
syntax is almost completely undocumented.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With