NSInvocation和按引用传递的参数

3
我正在使用NSInvocation来调用一个在编译时我不知道的方法。
这很有效,但我不知道如何传递NSError**类型的参数。
举个例子,假设我想从NSFileManager中调用方法-(BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error
代码看起来像这样:
NSFileManager *manager = [NSFileManager defaultManager];
SEL selector = @selector(removeItemAtPath:error:);
NSMethodSignature *signature = [manager methodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:manager];
[invocation retainArguments];
[invocation setSelector:selector];

NSString *path = ...;
[invocation setArgument:&path atIndex:2];
NSError *error = ...;
[invocation setArgument:&error atIndex:3];    // Passing NSError*, not NSError**

这是一个简单的例子。我避免添加错误检查代码,以使其更易于阅读。

另外,我不知道参数的类型,在编译时只接收 id 参数。

这是我尝试过但没有成功的方法。

id argument = ...
NSUInteger index = ...
const char *argType = [signature getArgumentTypeAtIndex:index];
if (strcmp(argType, "^@") == 0) {
    // object pointer
    id __strong *argumentPointer = &argument;
    [invocation setArgument:&argumentPointer atIndex:index];
}
else {
    [invocation setArgument:&argument atIndex:index];
}

说实话,我会尝试不同的方法。你很难正确处理一个NSError* __autoreleasing*参数。 - gnasher729
@gnasher729,你有什么建议? - Marcos Crispino
我可能会尝试使用块或处理多个函数的switch语句等。 - gnasher729
1个回答

0

找到了!

按引用传递参数需要声明为__autoreleasing

这是现在正在运行的代码:

id __autoreleasing argument = ...
NSUInteger index = ...
const char *argType = [signature getArgumentTypeAtIndex:index];
if (strcmp(argType, "^@") == 0) {
    // object pointer
    NSObject * __autoreleasing *argumentPointer = &argument;
    [invocation setArgument:&argumentPointer atIndex:index];
}
else {
    [invocation setArgument:&argument atIndex:index];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接