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