1

Say I have the following code:

var aString: String!
aString = "second"
print(aString)

This will print out some("second"). If I remove the ! from String this will just print out second. This addition of some(...) never used to happen in Swift 4, why is this suddenly happening now in 4.1? Is there ever a reason that I'd need to keep it as String! instead of String now?

EDIT

Just found a reason to keep the exclamation mark - if I have an if clause without an else, my code won't necessarily know that its been unwrapped. How do I handle this situation:

var aString: Int!
let aBool = true
if aBool {
    aString = 2
}

print(aString) // Prints some(2), crashes if I remove the `!`
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Tometoyou
  • 7,792
  • 12
  • 62
  • 108
  • 2
    Related: http://stackoverflow.com/questions/39537177/swift-3-incorrect-string-interpolation-with-implicitly-unwrapped-strings, https://stackoverflow.com/questions/39633481/implicitly-unwrapped-optional-assign-in-xcode-8 – Martin R Apr 01 '18 at 15:49

1 Answers1

0

String! is an implicitly unwrapped optional but it's still an optional.

The value will get unwrapped to a non-optional only in situations when it has to be unwrapped, e.g. when being passed to a function that cannot take an optional. However, print can accept an optional and String! will be treated just as String?.

This change actually happened in Swift 3 already as part of SE-0054.

In your example:

var aString: Int!
let aBool = true
if aBool {
    aString = 2
}

print(aString)

You should not be using an implicitly unwrapped optional because since it's a var, it get initialized to nil. You should either handle the unassigned case explicitly by using Int?, or, give it a default value:

let aString: Int
let aBool = true
if aBool {
    aString = 2
} else {
    aString = 0
}

print(aString)
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • Even simpler: `let aString = aBool ? 2 : 0`. BTW - why is an `Int` being named `aString`? – rmaddy Apr 01 '18 at 16:26
  • @rmaddy Yes, I know, didn't want to to major changes. – Sulthan Apr 01 '18 at 16:37
  • If I have an implicitly unwrapped optional as a value in a dictionary of type `[String : Any]`, it still doesn't unwrap, even though I specify it as the non-optional `Any`. Why is that? – Tometoyou Apr 01 '18 at 21:16
  • You can always assign `nil` to a dictionary safely. Getting a value from a dictionary always returns an optional. – Sulthan Apr 01 '18 at 21:21