How to pass an array to the objc method that var args expects (e.g. ...)

I have a method in the library that looks like this:

- (id)initWithSomeObjects:(NSString *)something, ... NS_REQUIRES_NIL_TERMINATION; 

I would really like to call it an array instead of var args, because the number of objects that I would like to transfer is changed.

Is there some way using performSelector or NSInvocation or objc_msgSend or something else that I can call the var args method with arguments coming from the array?

+3
source share
1 answer

There is no easy way to do this because, because the arguments passed are passed into the ugly details of the particular system that calls the ABI, and you should know, for example. how many arguments fit into registers and how to handle the remaining arguments, etc. And it will be associated with the assembly, and it is impossible to do in a general way.

Typically, any API that has a method or function that accepts such parameters will also either

  • Provide another method that accepts the va_list parameter (for example, -[NSString initWithFormat:] has -[NSString initWithFormat:arguments:] ). If so, then you can use this method to build va_list from the article you are linked to in the comments. (Even building va_list is systemic and non-portable. But at least it works on Mac and iPhone, and it's pretty simple to do and does not require assembly.)
  • Provide another method that accepts NSArray * or an array of C elements (for example, -[NSArray initWithObjects:] has -[NSArray initWithObjects:count:] )
  • Be able to add elements one by one, so that the overall effect is the same as passing them together to the varargs method (for example, the names of the varargs buttons at the end -[UIAlertView initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:] can be achieved by calling -[UIAlertView addButtonWithTitle:] multiple times).

If you have a varargs API that does not have one of the above, then this is a poorly developed API, and you should complain to the person who wrote it. If you are really faced with this situation, I assume that you could use something like libffi, which allows you to dynamically execute function calls and handle crazy system-dependent call mechanisms.

+5
source

Source: https://habr.com/ru/post/1497639/


All Articles