【问题标题】:Casting id to pointer to an NSError pointer (NSError **)将 id 转换为指向 NSError 指针的指针 (NSError **)
【发布时间】:2013-05-21 14:40:53
【问题描述】:

我有一个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 *
  • 我希望传入指针的人也可以使用错误对象。这是 Cocoa 中的常见模式,指针通常直接作为参数传入,而不是存储在数组中。
  • 传递给方法时很常见,是的,但是当您将 NSError 对象存储在数组中时,我看不出它是如何工作的。
  • 你需要一个地址来获取双指针,真的,不要像这样使用 NSArray 的指针存储机制。自动释放参数适用于本地人。
  • 我没有在生产代码中使用它。在我使用的单元测试框架 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; }];

标签: objective-c pointers nserror


【解决方案1】:

stub:withBlock: 方法或其任何支持基础结构都不能简单地将双指针填充到NSArray 中。数组不会接受非对象,指向对象的指针不是对象。还有其他事情发生。

这显然需要深入研究代码才能弄清楚。值在哪里被放入数组中?那在-[KWStub processInvocation:] 中,显然是使用OCMock 添加到NSInvocation 的方法getArgumentAtIndexAsObject: 完成的。在该方法中,调用使用开关来检查所请求参数的类型,并在必要时将其装箱。

这里的相关案例是最后一个,其中参数类型是^,意思是“指针”。这种论点包含在NSValue中;因此,您的 Block 收到的数组实际上包含的不是双指针本身,而是代表外部指针的 NSValue。您只需将其拆箱即可。

应该是这样的:

NSValue * errVal = array[1];
NSError * __autoreleasing * errPtr = (NSError * __autoreleasing *)[errVal pointerValue];

【讨论】:

  • 链接坏了! KWStub 到底去哪儿了?
  • 我在将 Kiwi 转换为 ARC 时移动了文件,该方法现在就在这里:github.com/allending/Kiwi/blob/master/NonARC/KWStub.m#L180
  • 谢谢!我应该链接到的 ARC 版本是否有相应的方法?
  • @JoshCaswell 感谢您的解决方案有效。我也尝试对memcpy 做同样的事情,它有点短,但我不确定它是否正确:memcpy([array[1] pointerValue], (void *)&error, sizeof(NSError **));(而不是你的两条线 + *errPtr = error;)你能看看吗?跨度>
猜你喜欢
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-15
相关资源
最近更新 更多