I am porting one of my iOS Apps to Swift3 / Xcode8. I have embedded a C library, which expects a function parameter of type:
char ***
In Swift2.3 this was translated into a:
UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>
So i could declare that pointer in my swift code like that:
let myPointer = UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>.alloc(1)
This worked well until i updated to Xcode8 with Swift3, now i am getting a compiler error:
Cannot convert value of type 'UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>>>' to expected argument type 'UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?>!'
Can i anybody help me to understand the changes in swift3? What does this Optional, Optional, Implicit Unwrapped Optional (?) mean in this context and how i can i declare a pointer with this type?
Try
let myPointer = UnsafeMutablePointer<
UnsafeMutablePointer<
UnsafeMutablePointer<Int8>?>?>.allocate(capacity: 1)
Alternatively you could also use the _Nonnull
annotation to keep the pointer as non-optional. Suppose the C function is void setPtr(char ***)
. You could write its declaration available to Swift via a bridging header as follows:
void setPtr(char * _Nonnull * _Nonnull * _Nonnull);
Then in your Swift code you can do something like this:
let myPointer = UnsafeMutablePointer<
UnsafeMutablePointer<
UnsafeMutablePointer<Int8>>>.allocate(capacity: 1)
setPtr(myPointer)
let myInt = myPointer.pointee.pointee.pointee
But what if setPtr(char *** ptr)
in C code, where _Nonnull
is not usable, does something like
*ptr = NULL;
? Then the Swift code will crash at runtime. However, using optionals you don't need the _Nonnull
annotation in the declaration of setPtr()
, your Swift code becomes
let myPointer = UnsafeMutablePointer<
UnsafeMutablePointer<
UnsafeMutablePointer<Int8>?>?>.allocate(capacity: 1)
setPtr(myPointer)
let myInt = myPointer.pointee?.pointee?.pointee
and it won't crash at runtime.
Thus the approach with optionals, enforced by Swift3 when you don't use _Nonnull
, is safer.