NSInvocation setArgument问题

时间:2012-11-28 09:34:51

标签: objective-c pointers nsinvocation

我需要使用NSInvocation动态调用方法。 在这里我尝试过:

NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[messageRecord.senderController class] instanceMethodSignatureForSelector:messageRecord.receiverAction]];

[invocation setSelector:messageRecord.receiverAction];
[invocation setTarget: messageRecord.senderController];
[invocation setArgument: &(message.data) atIndex:2];
[invocation invoke];

我需要提一下,messageRecord.senderController是调用哪个方法的对象,messageRecord.receiverAction是给这段代码的选择器。此外,message.data是类型(NSArray *)的对象并正确初始化。

这段代码给出了以下编译时错误

Address of property expression requested

当我按如下方式更改调用过程时,它按预期工作:

NSArray *dataArray = message.data;

[invocation setSelector:messageRecord.receiverAction];
[invocation setTarget: messageRecord.senderController];
[invocation setArgument: &dataArray atIndex:2];
[invocation invoke];

两者之间的唯一区别是:我创建了一个本地NSArray指针并为其分配了message.data。稍后,给出了新创建的指针的地址,而不是message.data本身。

为什么有效?无论如何有什么区别?

2 个答案:

答案 0 :(得分:2)

正如Shimanski Ahem所说,财产不是地址。属性只是一对getter和setter方法。而已。 getter和setter方法可以由您提供,也可以由编译器根据某些实例变量进行合成。如果它们是由您提供的,它们也可以基于某个实例变量,但您可以执行一些额外的逻辑;或者他们可以根据其他事情完全动态地生成值。因此,某些“实例变量”可能与该属性相对应。

如果合成了getter和setter,并且您知道它们所基于的实例​​变量(您可以从Synthesisize声明中获取;如果合成没有明确指定,则与属性名称相同;或者如果在最近版本的编译器中省略并隐式指定了Synthesis,则_data(前面带有下划线)。这就是Shimanski Artem所显示的内容。

但是,回过头来问一下,为什么你需要一个指向该值的指针?什么目的?如果您使用指向原始值的指针或指向该值副本的指针,它会有所不同吗?了解setArgument:方法的工作原理以及它需要指针的原因将有助于您回答其中的许多问题。 setArgument:允许您使用您选择的值设置调用中的一个参数,因此它真正关心。那么为什么不直接传递这个值呢?那么,它会是什么类型的?不同的类型在C中具有不同的大小,因此这是不可能的。所以相反,它要求你给出一个指向值的指针(适用于任何类型),然后从那里复制它。所以它只关心指向的,而不是特定的地址。这就是为什么(正如您所观察到的),当您想要将setArgument:用于不可寻址的东西时(如属性,或更复杂的表达式,或Objective-C ++中的this等),你可以简单地将它分配给一个临时变量并获取它的地址。

答案 1 :(得分:0)

您无法取得物业的地址。这是语言细节。您可以尝试以下表单:

[invocation setArgument: &(message->data) atIndex:2];