Swift3 изменяется на UnsafeMutablePointer

Я портирую одно из моих приложений для iOS на Swift3 / Xcode8. Я встроил библиотеку C, которая ожидает параметр функции типа:

char ***

В Swift2.3 это было переведено на:

UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>

Так что я мог бы объявить этот указатель в моем быстром коде так:

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

Это работало хорошо, пока я не обновил Xcode8 с Swift3, теперь я получаю ошибку компилятора:

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

Могу ли я кто-нибудь помочь мне понять изменения в swift3? Что означает этот Дополнительный, Дополнительный, Неявный развернутый Дополнительный (?) В этом контексте и как я могу объявить указатель с этим типом?

1 ответ

Решение

Пытаться

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, безопаснее.

Другие вопросы по тегам