0

我正在将我的一个 iOS 应用程序移植到 Swift3/Xcode8。我嵌入了一个 C 库,它需要一个类型的函数参数:

char ***

在 Swift2.3 中,这被翻译成:

UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>

所以我可以像这样在我的快速代码中声明该指针:

let myPointer = UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>.alloc(1)

在我使用 Swift3 更新到 Xcode8 之前,这一直很好,现在我收到编译器错误:

Cannot convert value of type 'UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>' to expected argument type 'UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?>!'

我可以帮助我了解 swift3 的变化吗?这个可选,可选,隐式未包装可选(?)在这种情况下意味着什么,我如何声明具有这种类型的指针?

4

1 回答 1

0

尝试

let myPointer = UnsafeMutablePointer<
    UnsafeMutablePointer<
    UnsafeMutablePointer<Int8>?>?>.allocate(capacity: 1)

或者,您也可以使用_Nonnull注释将指针保持为非可选。假设 C 函数是void setPtr(char ***). 您可以通过桥接头将其声明编写给 Swift,如下所示:

void setPtr(char * _Nonnull * _Nonnull * _Nonnull);

然后在您的 Swift 代码中,您可以执行以下操作:

let myPointer = UnsafeMutablePointer<
        UnsafeMutablePointer<
        UnsafeMutablePointer<Int8>>>.allocate(capacity: 1)
setPtr(myPointer)
let myInt = myPointer.pointee.pointee.pointee

但是,如果setPtr(char *** ptr)在 C 代码中,哪里_Nonnull不可用,会做类似的事情

*ptr = NULL;

? 然后 Swift 代码将在运行时崩溃。然而,使用可选项你不需要_Nonnull在声明中的注解setPtr(),你的 Swift 代码变成

let myPointer = UnsafeMutablePointer<
        UnsafeMutablePointer<
        UnsafeMutablePointer<Int8>?>?>.allocate(capacity: 1)
setPtr(myPointer)
let myInt = myPointer.pointee?.pointee?.pointee

并且它不会在运行时崩溃。因此,当您不使用 Swift3 时,使用可选选项的方法_Nonnull更安全。

于 2016-09-27T03:06:43.380 回答