(As @Hamish pointed out in a comment below, I misunderstood what the OP was really asking about. I'll leave my answer, however, as some curiosa and insights regarding !
type annotation, which may be relevant for future readers of this question)
For any type of String
optionals, their values needs to be unwrapped prior to using the failable init?(_ text: String)
initializer or Int
.
In your example, the variable npill
is an optional, as you've annotated its type with the !
specifier (which should be used with care). Quoting from the implemented evolution proposal SE-0054 [emphasis mine]
Appending !
to the type of a Swift declaration will give it optional
type and annotate the declaration with an attribute stating that it
may be implicitly unwrapped when used.
Hence, it's entirely legal to use npill
directly with the init?(_ text: String)
initializer of Int
, as it will be unwrapped (without any safety check for nil
content!) on-the-fly upon use.
// UNSAFE example!
var npill: String! = "42"
if let npillInt = Int(npill) {
/* ^^^^^^^^ ^^^^^- since 'npill' has a type annotated with
| '!', it will be unsafely unwrapped at
| this point
\
the optional binding here safely unwraps the return from
the failable Int initializer, but has nothing to do with
the unwrapping of 'npill' */
print(npillInt) // 42
}
// why unsafe? consider
npill = nil
if let npillInt = Int(npill) { // runtime exception!
// ...
}
Generally you should avoid using the !
annotation, however, unless you are entirely certain that the content of the resulting optional variable will never ever be nil
.
Leaving aside the cons of even using the !
annotation: you may implement a safe version of the unsafe example above, by overriding the unsafe implicit unwrapping with safe explicit unwrapping techniques. For a given optional variable declared using the !
annotation, we may still apply safe means to unwrap it, e.g. optional binding or using the nil coalescing operator. @appzYourLife has already showed one perfectly valid and safe way to handle the unwrapping and attempted type conversion of npill
using optional binding, so I'll simply include another example using the nil
coalescing operator instead:
// "safe" example (STILL: why use the `!` annotation?)
var npill: String! = "42"
if let npillInt = Int(npill ?? "x") {
/* ^^^^^ if 'npill' is 'nil', the Int initializer will
be given the value "x", which itself will lead
it to fail, which is safe here as we intend to
bind the result of the initialization to 'npillInt' */
print(npillInt) // 42
}
npill = nil
if let npillInt = Int(npill ?? "x") {
// ... doesnt enter
}
The consensus of the examples above is that if we're even slightly uncertain whether npill
can ever be nil
or not, we need to treat it as if it was just an optional not type annotated with !
(i.e. String?
); overriding the default unsafe unwrapping with safe means when working with the variable. In such a case, why would we even want to use the !
typ annotation at all, as it only brings fragility/danger to our application?