We've got api-endpoints format e.g
settings/user/%@/newSettings/%i
as well as serialized JSONResponse with parameters (string). [Parameters] are stored in NSArray because of JSONModel mapping - this can be strings, integers etc.
There isn’t a supported way to do this.
va_list
is defined by the C standard and that standard defines a
very limited set of operations on it (you can see the full list
here). None of those operations let you build a
va_list
except by applying
va_start
within a varargs function. Building a
va_list
by hand may work on some specific architectures but you will inevitably run into problems (either on new architectures, as the OS and compiler evolves).
I also want to clarify the example you showed above. Presumably, the end result is a call like this:
str = [SomeClass stringWithFormat:@"settings/user/%@/newSettings/%i"
array:@[ @"eskimo1", @42 ]
];
How did your old code work in the
%i
case? When you call
-getObjects:range:
, the value you get back is an
(NSNumber *)
not the
int
that’s specified by the
%i
format specifier.
Consider this code:
NSArray * arguments = @[ @"eskimo1", @42 ];
NSRange range = NSMakeRange(0, [arguments count]);
NSMutableData* data = [NSMutableData dataWithLength:sizeof(id) * [arguments count]];
[arguments getObjects:(__unsafe_unretained id *)data.mutableBytes range:range];
NSLog(@"%@", data);
which prints on my Mac:
<48520000 01000000 272a0000 00000000>
Remember that this is 64-bit big endian, so the actual values are:
0x0000000100005248
0x000000000000272a
The first one is an object pointer for
@"eskimo1"
, which makes sense and is compatible with the
%@
. The second is also an object pointer, but in this case it’s a tagged pointer for @42, and that won’t print properly if you feed it to
%i
(even if you ignore the fact that
%i
expects an
int
, which is 32-bits on our platforms).
If I were in your shoes I’d constrain the allowed format specifiers in the the format string and then manually parse the string, find the format specifiers, and then render that item of the array in a way that’s appropriate for that specifier. This would yield a bunch of advantages:
it will actually work (-:
it will allow to to check that the array contains the right number of arguments
it will allow you to type check each argument (at runtime, but that’s better than nothing)
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"