有没有办法让 NSInvocation 支持变量 parmas 函数行 [NSstring stringWithFormat:..]

Is there a way to Make NSInvocation surport variable parmas function line [NSstring stringWithFormat:..]

Apple 文档说 "NSInvocation does not support invocations of methods with either variable numbers of arguments or union arguments. "

我搜索了几个小时,有些人说 var_list 可以,但我试过了,不行

但我认为可能有一种方法可以对可变参数函数做同样的事情(反射),正如我提到的,[stringWithFormat:],

所以,我找到了一个方法,请阅读下面的代码。

            @interface INTObj : NSObject
    @property (nonatomic, assign)   int  realvalue
    @end

    @interface FloatObj : NSObject
    @property (nonatomic, assign)   float  realvalue
    @end

    // here ,the selectorName is only know in runtime
    NSString *selectorName = @"stringWithFormat:";
    SEL selector = NSSelectorFromString(selectorName);
    typedef id (*Obj_Imp)(id,SEL,...);
    Method md =  class_getClassMethod(obj, selector);  // here, obj means NSString
    Obj_Imp fun =  (Obj_Imp )method_getImplementation(md); // stringWithFormat:...

    NSString *arg1 = @"hello  %f  %d";

    FloatObj *fo = [[FloatObj alloc] init];
    fo.realvalue = 11.3;

    INTObj *io = [[INTObj alloc] init];
    io.realvalue = 5;


    NSObject *arr[3] = {arg1, fo,io};

   // it cracks  . exc_bad_Access code = 1
   NSString *result = fun(obj , selector, arr[0], [arr[1] realvalue],[arr[2] realvalue]) ;

   // it works but i cant do this ,because i don't know the type of the 4th parameters  at Runtime
   NSString *result = fun(obj , selector, arr[0],[(FloatObj *)arr[1] realvalue],[arr[2] realvalue])

为什么第二次调用函数 "fun" 有效,而第一次调用失败?

有更好的方法吗?

这与NSInvocation无关,直接调用方法实现。如果您直接调用该方法,您应该得到相同的未定义行为:

NSString *result = [NSString stringWithFormat:arr[0], [arr[1] realvalue], [arr[2] realvalue]];

甚至是常规函数:

NSLog(arr[0], [arr[1] realvalue], [arr[2] realvalue]);

在 C(和 Objective-C)中,每个表达式都必须有一个编译时类型。编译器需要知道这个编译时类型才能正确编译代码。

那我问你,[arr[1] realvalue]的编译时类型应该是什么?是int吗?是float吗?编译器会根据它的类型做不同的事情。例如,如果是 float,C 标准表示传递给可变参数的 float 将被提升为 double。在可变参数中传递 intdouble 的调用约定是不同的(事实上,这两种类型具有不同的大小)。并且 +[NSString stringWithFormat:] 期望你传递的东西的编译时类型与你在格式字符串中给它的格式说明符相匹配,否则会有未定义的行为。

从您的格式字符串来看,您似乎希望 [arr[1] realvalue] 参数为 floatdouble,因为您使用了 %f。由于 FloatObj 是 class 的 realvalue 方法 returns float,似乎将 arr[1] 转换为 FloatObj * 是正确的去做。