I need to create in an iOS application a fake va_list
to pass to a NSString initWithFormat:arguments:
function, this is my code:
NSArray *fixedArguments = [[NSArray alloc] initWithArray:arguments];
NSRange range = NSMakeRange(0, [fixedArguments count]);
va_list fakeArgList = (va_list)malloc(sizeof(NSString *) * [fixedArguments count]);
__unsafe_unretained id *ptr = (__unsafe_unretained id *)fakeArgList;
[fixedArguments getObjects:ptr range:range];
content = [[NSString alloc] initWithFormat:outputFormat
arguments:(va_list)fakeArgList];
free(fakeArgList);
The compiler complains with this message on the cast line:
error: cast of a non-Objective-C pointer type 'va_list' (aka 'char *') to '__unsafe_unretained id *' is disallowed with ARC
The getObjects:range:
function is defined as follows:
- (void)getObjects:(id __unsafe_unretained [])objects range:(NSRange)range;
I've tried everything but still can't get rid of this error...
Is there a solution for creating a fake va_list
with ARC enabled? What am i doing wrong?
EDIT: This no longer works. As foreseen in the initial answer, the ABI appears to have changed out from under this answer
Played around for a bit and got it to work -- Double checked for leaks or abandoned memory and didn't see any.
I like to (ab)use NSMutableData like this to get retain/release semantics on an arbitrary chunk of memory -- It's not necessarily relevant to the issue at hand, but it's a neat little trick.
As a note to future readers: Faking up a va_list like this happens to work with the current ABI for MacOS and iOS, but in general it's not portable, and not a good approach.
Its possible if you are willing to add a little bit of swift to your project!
The important bit is the mapping of NSArray to
[CVarArgType]
which is the swift equivalent forva_list
. If you try to cast[AnyObject]
to[CVarArgType]
you cause run time crashes, but with themap
we can explicitly make the needed list.The rest of the code is the wrapper I made so that I can call this from obj-c. You could make a wrapper for any obj-c function that you want to call in this way.