3

似乎 Xcode 9.3 确实解决了我遇到的一个问题,但在 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?那么第二个函数调用将毫无怨言地编译。

这是另一个与隐式展开选项相关的挥之不去的 Swift 错误,还是UnsafeMutablePointer预计这种情况不会像inout现在的版本那样工作?有没有相对干净的解决方法?


背景:

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

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

也就是说,这似乎是隐式解包选项的合法用例,我想知道为什么我仍然不能在这里使用一个。

4

1 回答 1

2

恐怕这是隐式展开的选项(IUO)的另一个挥之不去的错误。

虽然它已经被修复(几乎可以肯定是由于最近的工作从类型系统中完全删除 IUO)——它在最新的开发快照中编译,因此将使其成为 4.2(最终从 master 重新分支是 4 月 20 日)。

在 4.2 发布之前,一种可能的解决方法是使用转发计算变量来将 IUO 视为强 Optional 类型:

class SomeClass {}

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

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

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

于 2018-04-19T19:44:42.720 回答