-[NSInvocation getReturnValue:] with double value produces 0 unexpectedly

后端 未结 4 618
無奈伤痛
無奈伤痛 2021-02-05 12:22

I am trying to call a method that returns a double using NSInvocation. But I found that it does not working in 64 bit iOS apps. It works on on OS X, in

4条回答
  •  Happy的楠姐
    2021-02-05 13:11

    Fix based on @TomSwift answer.

        - (void)testInvocation
        {
            NSInvocation *invocation = [[self class] invocationWithObject:self selector:@selector(getAFloat)];
    
            [invocation setTarget:self];
            [invocation invoke];
    
            double d;
            [invocation getReturnValue: &d];
            NSLog(@"d == %f", d);
    
            return YES;
        }
    
        + (NSInvocation *)invocationWithObject:(id)object selector:(SEL)selector
        {
            NSMethodSignature *sig = [object methodSignatureForSelector:selector];
            if (!sig) {
                return nil;
            }
    
        #ifdef __LP64__
            BOOL isReturnDouble = (strcmp([sig methodReturnType], "d") == 0);
            BOOL isReturnFloat = (strcmp([sig methodReturnType], "f") == 0);
    
            if (isReturnDouble || isReturnFloat) {
                typedef struct {double d;} doubleStruct;
                typedef struct {float f;} floatStruct;
    
                NSMutableString *types = [NSMutableString stringWithFormat:@"%s@:", isReturnDouble ? @encode(doubleStruct) : @encode(floatStruct)];
                for (int i = 2; i < sig.numberOfArguments; i++) {
                    const char *argType = [sig getArgumentTypeAtIndex:i];
                    [types appendFormat:@"%s", argType];
                }
    
                sig = [NSMethodSignature signatureWithObjCTypes:[types UTF8String]];
            }
        #endif
    
            NSInvocation *inv = [NSInvocation invocationWithMethodSignature:sig];
            [inv setSelector:selector];
            return inv;
        }
    

提交回复
热议问题