kar*_*ten 1 arguments class dynamic objective-c selector
我正在尝试使用服务器连接器对象实现JSON-RPC解决方案,该服务器连接器对象从服务器获取可用功能列表
NSDictionary *functions = [server
callJSONFunction: @"exposedFunctions" arguments: nil];
Run Code Online (Sandbox Code Playgroud)
这是一个简化的描述,因为callJSONFunction实际上触发了异步NSURLConnection.
函数列表的一个元素由一个描述目标c选择器的字符串,将使用上述机制调用的原始函数名,函数签名和一个可选的参数名数组组成.
例如,函数列表可能如下所示:
(
@"someFunctionWithArgumentOne:argumentTwo:" =
{
signature = @"@@:@@",
functionName = @"someFunction",
arguments = ( @"arg_one", @"arg_two" )
},
@"anotherFunction" =
{
signature = @"@@:",
functionName = @"anotherFunction"
}
)
Run Code Online (Sandbox Code Playgroud)
成功检索功能列表后,选择器将class_addMethod在循环中添加到服务器连接器实例中:
for ( NSString *selectorName in functions ) {
SEL aSelector = NSSelectorFromString ( selName );
IMP methodIMP = class_getMethodImplementation (
[ self class ], @selector ( callerMethod: ) );
class_addMethod ( [ self class ], aSelector, methodIMP, "v@:@@@@" );
}
Run Code Online (Sandbox Code Playgroud)
where callerMethod:用于组成实际请求的包装函数,包括作为NSString的函数名和表单的NSDictionary
{ @"argument1_name" = arg1, @"argument2_name" = arg2, ... }
Run Code Online (Sandbox Code Playgroud)
因此签名"v @:@@".然后callerMethod callJSONFunction在服务器上调用.
经过这个令人筋疲力尽的介绍(我的不好,我只是不知道,如何缩短它)我终于明白了:为了涵盖不同数量的参数的可能性,我定义了callerMethod就像
- (void) callerMethod: (id)argument, ... { }
我使用va_*宏从中stdarg.h获取传递的参数.但是当我通过调用测试机制时
[serverConnector someFunctionWithArgumentOne: @"Argument 1"
argumentTwo: @"Argument 2" ];
Run Code Online (Sandbox Code Playgroud)
返回的第一个参数id arg = va_arg ( list, id);总是@"Argument 2"!
我真的很感激所有理论和解释为什么会发生这种情况.这件事真让我疯了!
bbu*_*bum 15
Var-args不会映射到常规参数传递非常整齐.参数的编码实际上是特定于体系结构的,并且充满了非常有趣的细节,有时看起来它们是自相矛盾的(直到你发现关于规则的一个例外的注释,使整个事物连贯一致).如果你真的想要一个好的阅读[讽刺意图],那么去看看ppc64如何处理长双打; 有些情况下,double的一半将在寄存器中,另一半在堆栈中.Whee!
上面的长,由于疤痕而略带泡沫,段落就是说你不能透明地将调用从一个函数转发到另一个函数,其中两个函数采用不同的参数.由于Objective-C方法实际上只是一个函数,因此方法也是如此.
相反,使用NSInvocation,因为它旨在隐藏包含任何给定平台ABI的参数编码的所有深奥细节.
但是,在您的情况下,您可以通过定义一组定义所有可能的论证组合的函数来逃避class_addMethod().您甚至不需要创建字典,因为您可以使用该dlsym()函数来查找正确的函数.即
id trampolineForIdIdSELIdIdInt(id self, SEL _cmd, id obj1, id obj2, int) {
... your magic here ...
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以将类型字符串"@@:@@ i"转换为该函数名称并将其传递给dlsym,获取结果并使用class_addMethod()....
我确实觉得有义务也提到这本书,因为它是一种"哇......男人......如果我们将类表示为被称为元类的对象,它们本身就被表示为类,那么我们就可以将宇宙重新定义为元类和类"这一思路的终极目标.
| 归档时间: |
|
| 查看次数: |
903 次 |
| 最近记录: |