Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

swift: forced type modifier "!" - why is (was) it used in UIKit API (now anachronistic)

Edit: The intent of this question was to understand the use of the implicit optional operator "!" in the early UIKit API updates, specifically if a function was declared as returning a type expected to be non optional, why use optional at all, and if it was optional, why not use the optional "?" operator. The semantics of "!" were always clear though.

As time later showed, it was a matter of Apple auditing the API to make the optionality more precise, using ? for truly optional types, and using non optional types when they were in fact non optional. This was a hold-over of the original Objective-C signatures which were often ambiguous.


The swift documentation explains the purpose of the ! unboxing operator on optional types,

var optionalString : String? = "optional"
var regularString: String = optionalString!

but they have used it on type definitions themselves (String!), without an explicit explanation that I can find.

Example:

func takesBang(value:String!) -> String {
    if !value {
        return "nil value, without the safe syntax"
    }

    return "This works"
}

var unsafe:String!
takesBang(unsafe) // yields "nil value, without the safe syntax"

The String! type does not force an unboxing of the optional type, but only seems to remove the need for optional syntax (?.). Apple uses this in their own examples, but it seems to only negate the optional safety (pointer) mechanisms.

Can anybody explain the purpose / motivation? This seems generally unsafe as the caller won't have to check or at least think about their value.

like image 574
Chris Conover Avatar asked Jun 05 '14 22:06

Chris Conover


2 Answers

The Language Reference states that both, ? as also !, when used on var declarations are only syntactic sugar (meaning they are replaced by the compiler during parsing). They map to Optional<T> (?) and ImplicitlyUnwrappedOptional<T> (!) respectively.

While you have to use the if let maybeNil = someVar? { ... } syntax for variables of type Optional<T>, you don't have to do so with the implicitly unwrapped optionals (as the name already implies). As the poster in https://stackoverflow.com/a/24071003/1599345 already mentioned, implicitly unwrapped optionals are meant to be used with legacy Objective-C APIs, since those don't provide enough information for Swift.

So as a short recap:

var foo : SomeType? // should be read as var foo : Optional<SomeType>
var bar : SomeType! // should be read as var bar : ImplicitlyUnwrappedOptional<SomeType>

The usage of ? and ! when working with actual values in variables is actually a mapping that can be read in this way, analogous to the declarations above:

foo?.somemethod() // if let maybeFoo = foo { maybeFoo.somemethod() }

foo!.somemethod() /* # Yeah I know for sure, that this is NOT nil ever ever… just call `somemethod` and kill me at runtime if it doesn't work out.
like image 142
punycode Avatar answered Nov 13 '22 00:11

punycode


It is generally unsafe, but is used for imported Objective-C APIs, which are already unsafe in that way and don't expose enough information to decide whether they should be Optional or non-Optional.

In non-imported APIs, I wouldn't expect it to be used much.

like image 3
Catfish_Man Avatar answered Nov 12 '22 23:11

Catfish_Man