如何使用将指向对象的指针作为参数的方法创建NSInvocation对象

时间:2012-04-03 03:58:11

标签: ios cocoa-touch automatic-ref-counting nserror nsinvocation

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

- (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:选项:错误:最后一个参数期望接收指针而不是对象。因此,执行以下操作无效 -

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

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

3 个答案:

答案 0 :(得分:3)

您创建的参数与您传递给方法的任何其他参数相同。

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

NSError **errorPointer

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

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

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

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

重要的是要意识到应该为您创建的参数考虑范围并将其传递给您的调用。看看我问here的类似问题。

答案 1 :(得分:2)

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

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

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

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

引用我这个答案的参考文献:

NSInvocation & NSError - __autoreleasing & memory crasher

Automatic Reference Counting: Pointer to non-const type 'NSError *' with no explicit ownership

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

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

答案 2 :(得分:0)

参数类型为NSError **,您可以从中获取要写入错误的NSError *的地址。要在NSInvocation中设置参数,您需要将参数值的地址传递给setArgument:,因此您需要将NSError **放在变量中(我称之为{ {1}}此处),并将其地址(将为errPointer)传递给NSError ***。之后您不需要setArgument:变量。

errPointer