我需要使用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本身。
为什么它会起作用?到底有什么不同呢?
发布于 2012-11-29 05:57:32
正如Shimanski提到的,房产不是有地址的东西。属性只是一对getter和setter方法。就这样。getter和setter方法可以由您提供,也可以由编译器基于某个实例变量合成。如果它们是由您提供的,它们也可以基于某个实例变量,但您需要执行一些额外的逻辑;或者,它们可以完全基于其他内容动态生成值。因此,可能不存在与该属性对应的某个“实例变量”。
如果getter和setter是综合的,并且您知道它们所基于的实例变量(可以从synthesize声明中获得;如果synthesize没有显式指定,则该变量与属性名称相同;或者,如果在编译器的最新版本中省略并隐式指定了synthesize,则该变量为_data (前面带有下划线)。这就是Shimanski Artem所展示的。
然而,退一步问一下,为什么你首先需要一个指向这个值的指针?目的是什么?如果使用指向原始值的指针,还是指向该值的副本的指针,是否会有所不同?理解setArgument:方法是如何工作的,以及它为什么需要指针将帮助您回答其中的许多问题。setArgument:允许您将调用中的一个参数设置为您选择的值,因此它真正关心的是值。那么为什么不让你直接传递这个值呢?那么,它是什么类型的呢?不同的类型在C中有不同的大小,所以这是不可能的。因此,它要求您提供一个指向该值的指针(该指针适用于任何类型),然后从那里复制该值。所以它只关心指向的值,而不关心特定的地址。这就是为什么(正如你所观察到的),当你想将setArgument:与一些不可寻址的东西(比如一个属性,或者更复杂的表达式,或者Objective-C++中的this,等等)一起使用时,你可以简单地将它赋给一个临时变量并获取该临时变量的地址。
发布于 2012-11-28 18:02:36
你不能取一个房产的地址。这是语言的细节。您可以尝试此表单:
[invocation setArgument: &(message->data) atIndex:2];https://stackoverflow.com/questions/13601902
复制相似问题