Getting parameters from a common method

I am trying to get parameters at runtime from some random method that is being called in my class. Before arm64(in armv7and armv7s) this can be done using the 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 is quite easy and clean. We simply pass all incoming calls to one single implementation, which can collect parameters from it and return them.

In arm64yet va_listit works well, but in this context of the first parameter va_arg(arguments, id)is the current instance of the class ( self). After the second call, he stopped with help EXC_BAD_ACCESS. Therefore, I think that he did not even find the first parameter (c va_start(arguments, obj1)).

, va_list arm64 , dynamicMethod: ( ). , - ( arm64, ).

, - .

+4
3

PR Github, @-gazdag. :

- (void)forwardInvocation:(NSInvocation *)inv {
    NSUInteger n = [[inv methodSignature] numberOfArguments];

    NSMutableArray *parameterList = [[NSMutableArray alloc] init];
    for (NSUInteger i = 0; i < n - 2; i++) {
        id __unsafe_unretained arg;
        [inv getArgument:&arg atIndex:(int)(i + 2)];
        if (!arg) {
            arg = [NSNull null];
        }
        [parameterList addObject:arg];
    }
    [self dynamicWebServiceCallWithArguments:parameterList forInvocation:inv];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSUInteger numArgs = [[NSStringFromSelector(aSelector) componentsSeparatedByString:@":"] count] - 1;
    return [NSMethodSignature signatureWithObjCTypes:[[@"@@:@" stringByPaddingToLength:numArgs + 3 withString:@"@" startingAtIndex:0] UTF8String]];
}

- (void)dynamicWebServiceCallWithArguments:(NSMutableArray *)parameterList forInvocation:(NSInvocation *)invocation {
   ... 
   id result = [self executeDynamicInstanceMethodForSelector:invocation.selector parameters:parameterList prepareToLoadBlock:prepareToLoadBlock success:successBlock failure:failureBlock];
   [invocation setReturnValue:&result];
}

. , . , =)

+4

, , , (32 ) arm64 . , , .

" ". , , - , .

. ARM arm64 ARM ( 64 ).

; , , .

, "" , , - , , . JSCocoa , , "Burks Pool" ( , )

libffi iOS: https://github.com/roupam/Objective-C-NuREPL-for-iOS/tree/master/Remote/libffi

, : - [NSInvocation getReturnValue:] 0

+7

A . :

- (void)requestSucceeded 
{
    NSLog(@"requestSucceeded");
    id owner = [fbDelegate class];
    SEL selector = NSSelectorFromString(@"OnFBSuccess");
    NSMethodSignature *sig = [owner instanceMethodSignatureForSelector:selector];
    _callback = [NSInvocation invocationWithMethodSignature:sig];
    [_callback setTarget:owner];
    [_callback setSelector:selector];
    [_callback retain];       // <------ See the partial doc attached

    [_callback invokeWithTarget:fbDelegate];
}

NSInvocation:

. NSInvocation , keepArguments .

, , , 2 , ., : ( )

0 1 self _cmd, ; . 2 .

exmaple, facebook .

This code dynamically calls the delegate function, reading it from the delegate interface and calling it with / without arguments.

The idea behind this solution is that it does not require an external Encoding link, plus you have to save _callbackto avoid EXC_BAD_ACCESS, and yes, it is a bit easier.

Hope this helps!

0
source

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


All Articles