为什么我不能将一个隐式解包的可选项作为UnsafeMutablePointer传递?

时间:2018-04-19 19:05:36

标签: swift pointers optional inout

似乎Xcode 9.3确实修复了one issue I was having,但是在Swift 4.1中,这段代码的后半部分仍然无法编译:

var obj: SomeClass!    ; class SomeClass {}

func inoutFunc(_: inout SomeClass?) {}
inoutFunc(&obj)     // works

func pointerFunc(_: UnsafeMutablePointer<SomeClass?>) {}
pointerFunc(&obj)  // <-- COMPILER ERROR

现在对inoutFunc的调用很好,但是对pointerFunc的调用仍然给我一个错误:

  

无法使用类型为'(inout SomeClass!)'的参数列表调用'pointerFunc'

或者在原始背景下:

  

无法传递“ActualClass”类型的不可变值?作为inout参数

类似于我的Swift 4.0问题(inoutFunc也没有编译)如果我将声明更改为var obj: SomeClass?,那么第二个函数调用将编译而不会抱怨。

这是另一个与Implicitly Unwrapped Optionals相关的挥之不去的Swift错误,或者这个UnsafeMutablePointer情况不会像inout版本那样起作用吗?是否有相对干净的解决方法?

背景:

在实际代码中,pointerFunc调用是一个Apple框架函数,可以初始化实例或返回错误状态。

由于我已经guard AppleFrameworkInitializer(&obj) == noErr else { /* … */ },我不想处理从临时可选项重新分配,或者必须经常在后面的所有代码中解包obj!

也就是说,这似乎是Implicitly Unwrapped Optionals的合法用例,我想知道为什么我仍然不能在这里使用。

1 个答案:

答案 0 :(得分:2)

我担心这是隐含未解决的选项(IUO)的另一个挥之不去的错误。

它已经被修复了(几乎可以肯定是the recent-ish work to completely remove IUOs from the type system的结果) - 它在最新的dev快照中进行编译,因此将它变成4.2(从master到4月20日的最终重新分支)。

在4.2推出之前,一种可能的解决方法是使用转发计算变量,以便将IUO视为强大的可选类型:

class SomeClass {}

var obj: SomeClass!
var _optionalObj: SomeClass? {
  get { return obj }
  set { obj = newValue }
}

func pointerFunc(_: UnsafeMutablePointer<SomeClass?>) {}
pointerFunc(&_optionalObj)

(也就是说,假设您指针指向一个临时值即可 - 即您不依赖于指针值是稳定的还是唯一的,例如,如果这是指例如,用作关联对象键)