将id强制转换为指向NSError指针的指针(NSError **)

4

我有一个存储在数组中的 NSError **(所以我可以这样获取它 array [0]),我想把它转换成变量:

NSError * __autoreleasing * errorPointer = (NSError * __autoreleasing *)array [0];

这样我就可以访问底层对象,如 *errorPointer

但是,Xcode 抱怨说 Cast of an Objective-C pointer to 'NSError *__autoreleasing *' is disallowed with ARC。有没有不关闭 ARC 的方法来访问此对象?


为什么你要存储为 NSError ** 而不是只用 NSError * - trojanfoe
我希望传递指针的人也能使用错误对象。这是Cocoa中常见的模式,指针通常直接作为参数传递,而不是存储在数组中。 - Stepan Hruda
当传递给方法时,这是很常见的,但我不明白当您将NSError对象存储在数组中时它是如何工作的。 - trojanfoe
你需要使用地址运算符来获取双重指针,而且真的不要像这样搞NSArray的指针存储机制。自动释放参数只适用于本地变量。 - CodaFi
我没有在生产代码中使用它。在我使用的Kiwi单元测试框架中,有一种方法可以让你存根一个选择器并用任何块替换其代码。它将所有方法参数传递到一个数组中:[beer stub:@selector(drinkByHand:error:) withBlock: id ^(NSArray *params) { Hand *hand = (Hand *)params[0]; // here I want to get the error and fill it in, so I can simulate a failure; return nil; }]; - Stepan Hruda
1个回答

8
stub:withBlock:方法及其支持基础设施都不能简单地将双指针塞入NSArray中。该数组不接受非对象类型,指向对象的指针也不是一个对象。这里还有其他问题。
这显然需要深入代码中进行研究。值放入数组中的位置在哪里?这在-[KWStub processInvocation:]中,并且它似乎使用OCMock添加到NSInvocation中的一个方法getArgumentAtIndexAsObject:来完成。在该方法中,调用使用开关检查所请求的参数类型,并在必要时将其打包。
这里相关的情况是最后一种情况,其中参数类型为^,表示“指针”。这种参数被封装在NSValue中。因此,通过您的块接收到的数组实际上包含代表外部指针的NSValue,您只需要将其取消封装即可。
应该如下所示:
NSValue * errVal = array[1];
NSError * __autoreleasing * errPtr = (NSError * __autoreleasing *)[errVal pointerValue];

链接断了!KWStub去哪里了? - jscs
我在将Kiwi转换为ARC时移动了文件,该方法现在在这里:https://github.com/allending/Kiwi/blob/master/NonARC/KWStub.m#L180 - Stepan Hruda
谢谢!ARC版本是否有相应的方法需要链接到? - jscs
1
@JoshCaswell 谢谢,你的解决方案有效。我也尝试使用memcpy做同样的事情。它更短,但我不确定它是否正确:memcpy([array[1] pointerValue], (void *)&error, sizeof(NSError **));(代替你的两行代码+ *errPtr = error;)。你能看一下吗? - igrek

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