4

我想使用一个将指向 NSError 对象的指针作为参数的方法创建一个 NSInvocation 对象。这方面的一个例子是方法 -

- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)mask error:(NSError **)errorPtr

我明白我会像这样设置我的调用

NSData *myData = [[NSData alloc] init];

SEL writeToFileSelector = @selector(writeToFile:options:error:);
NSMethodSignature *signature = [NSData instanceMethodSignatureForSelector:writeToFileSelector];

NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:myData];
[invocation setSelector:writeToFileSelector];

NSString *string = [NSString stringWithFormat:@"long cat"];
NSDataWritingOptions *dataOptions;
*dataOptions = NSDataWritingFileProtectionComplete;

[invocation setArgument:&string atIndex:2];
[invocation setArgument:&dataOptions atIndex:3];

对于 writeToFile:Options:Error:最后一个参数期望接收指针而不是对象。因此,执行以下操作不起作用 -

NSError *err = nil;
[invocation setArgument:&err atIndex:4];

解决方案可能是创建指向指针的指针似乎是合乎逻辑的,但这会导致编译器警告。我不确定如何正确执行它并且不会产生内存管理问题。

4

3 回答 3

3

您创建的参数与您传递给该方法的任何其他参数一样。

正如您所指出的,方法签名需要一个 NSError ** 作为其最后一个参数(索引 4)。所以,你需要声明一个,但有一点问题。

NSError **errorPointer

给你一个指向 NSError 变量的变量。但是,由于您没有告诉它指向任何变量,所以它指向 nil。因此,当您触发调用时,选择器将无法更改错误指针指向的变量。换句话说,它就像调用[myData writeToFile:string options:dataOptions error:NULL].

因此,您还需要声明一个 NSError 变量,并将其地址分配为您的 errorPointer 应指向的变量:

NSError *error;
NSError **errorPointer = &error;

现在您可以将 errorPointer 作为参数传入,如果在调用该方法时出现问题,您可以稍后检查它。查看NSInvocation上的这篇文章以获得更多帮助(Mark Dalrymple指出博客文章的提示)

同样重要的是要意识到,应该为您创建并传递给您的调用的参数考虑范围。看看我在这里问的一个类似问题。

于 2012-04-04T13:05:53.763 回答
2

edelaney05 接受的答案很棒,但我认为它需要对 ARC 稍作调整。(我还不能添加评论,所以创建一个新的答案来记录我的发现)

照原样,我得到了编译错误:“指向非常量类型'NSError *'的指针,没有明确的所有权”

我对此进行了研究,发现我需要:

 NSError * __autoreleasing error = nil;
 NSError * __autoreleasing *errorPointer = &error;

导致我得到这个答案的参考资料:

NSInvocation & NSError - __autoreleasing & memory crasher

自动引用计数:指向非 const 类型“NSError *”的指针,没有明确的所有权

http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

“__autoreleasing 用于表示通过引用 (id *) 传递并在返回时自动释放的参数。”

于 2013-04-16T02:39:56.350 回答
0

参数类型是NSError **,您可以通过获取NSError *要写入错误的地址来获得。要在 an 中设置参数NSInvocation,您需要将参数值的地址传递给setArgument:,因此您需要将您的变量放入NSError **一个变量(我在这里称其为errPointer),然后将其地址(将是 an NSError ***)传递给传给setArgument:. 之后您不需要该errPointer变量。

NSError *err = nil;
NSError **errPointer = &err;
[invocation setArgument:&errPointer atIndex:4];
于 2012-05-11T18:53:17.583 回答