14

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.

Shruti Thombre
  • 989
  • 4
  • 11
  • 27
Chris Conover
  • 8,889
  • 5
  • 52
  • 68

3 Answers3

20

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.
Community
  • 1
  • 1
punycode
  • 556
  • 5
  • 8
3

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.

Catfish_Man
  • 41,261
  • 11
  • 67
  • 84
-1

It turns out that this was just an oversight on Apple's part, they have been auditing classes and updating the return types since Beta 5.

From the Beta 6 release notes:

"A large number of Foundation APIs have been audited for optional conformance, removing a significant number of implicitly unwrapped optionals from their interfaces. This clarifies the nullability of their properties and arguments / return values of their methods. This is an ongoing effort since beta 5."

Chris Conover
  • 8,889
  • 5
  • 52
  • 68
  • This answer is interesting, but something less than an explanation of `!` as alias for `ImplicitlyUnwrappedOptional`. When we know that a value SHOULD definitely be non-nil (and we would want a loud fail, which we should also want) then it's useful to use this. @punycode's answer is more useful. – ocodo Apr 15 '18 at 00:58
  • @ocodo, The question really was, given the mechanism, why? And the answer remains that the semantics of existing API was unknown or unclear at the time, though they have since moved towards auditing and clarifying it, as far as I can tell. Having had read the Swift book, I did understand the mechanism though - what they meant and how they were mapped to the underlying optional types, just not why they would have an unclear API, but it seemed to be a transitional process for them. – Chris Conover Apr 16 '18 at 04:05
  • Thank you for the reply. I think the question itself is a little muddled, since the title asks, what is `!` and then the OP finally gets to a point of asking "why?" in the body. For those looking for the definition this question pops up. So I agree that your answer does seem to address the OP, it doesn't reflect the question that people search for. If I could, I'd withdraw my downvote, the confusion is clearly not your fault. – ocodo Apr 17 '18 at 12:26