I'm trying to receive parameters in runtime from some random method that is invoked on my class. Before arm64
(on armv7
and armv7s
) it can be done with following code:
@interface MyClass
// It does not matter what method, we declare it for compiler only
- (id)methodWithFirstParameter:(id)firstParam secondParameter:(id)secondParam;
@end
@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)sel {
[self addDynamicCallForSelector:sel];
return YES;
}
+ (void)addDynamicCallForSelector:(const SEL)selector {
const char *encoding;
IMP implementation;
implementation = [self instanceMethodForSelector:@selector(dynamicMethod:)];
Method newMethod = class_getInstanceMethod([self class], @selector(dynamicMethod:));
encoding = method_getTypeEncoding(newMethod);
class_addMethod([self class], selector, implementation, encoding);
}
- (id)dynamicMethod:(id)obj1, ... {
int parameterCount = [[NSStringFromSelector(_cmd) componentsSeparatedByString:@":"] count] - 1;
NSMutableArray *parameterList = [[NSMutableArray alloc] initWithCapacity:parameterCount];
va_list arguments;
va_start(arguments, obj1);
for (int i = 0; i < parameterCount; i++) {
id parameter = (i == 0) ? obj1 : va_arg(arguments, id);
if (!parameter) {
parameter = [NSNull null];
}
[parameterList addObject:parameter];
}
va_end(arguments);
return parameterList;
}
It's pretty easy and clean. We just pass all incoming invocation to one single implementation that can gather parameters from it and return them.
In arm64
however, va_list
works good, but in such context, the first parameter from va_arg(arguments, id)
is current instance of class (self
). After second call it's stopped with EXC_BAD_ACCESS
. So I think it did not even find first parameter (with va_start(arguments, obj1)
).
Also notice that va_list functionality works fine on arm64
in case I invoke dynamicMethod:
directly (and manually set number of arguments). My wild guess that it does not work because of wrong method encoding (it does not magically convert one method into another with different number of parameters on arm64
like it was before).
You can look all code here, it's basically web service part of this solution.