I no longer see Xcode complaining that certain things need optionals (the "?"). Now it is always forced unwrapped (the bang "!"). Is there any reason to use optionals anymore when we now have forced unwrap?
I don't really know what you mean when you write that you no longer see Xcode complaining that "certain things need optionals. Now it is always forced unwrapped". These two sentences contradict eachother:
Perhaps what you ment was that Xcode seemingly complains less often when you actually do force unwrap optionals, or, as a bad habit of Xcode, prompts you to force unwrap things to avoid compile time errors. This is generally because Xcode cannot know at compile time that you just wrote code that will break your app at runtime.
Xcode may seemingly at times have only one single purpose with its "smart hints": namely to absolve compile time errors. If you try to assign the value of a String?
type (optional String
) to String
type, Xcode will prompt you with a compiler error and ask if you ment to add the forced unwrapping operator !
. Smart Xcode, you say? Meh, Xcode is good for many things, but deciding how you unwrap your optionals is, not yet anyway, one of them. So even with Xcode prompting you for all kinds of things: if you can use optional chaining, do.
There might be exception, of course. For the controller part of the MVC design pardigm, you usually use the as!
operator to do "forced conversion" (casting), with Xcode sometimes telling you to explicitly to use as!
instead of as
, e.g. "Did you mean as!
... ?". In these situations, Xcode can sometimes actually know what its doing and infer that you are trying to cast, as an example, a custom UIViewController
class instance to type UIViewController
, i.e., to it's parent class. I'd say that this is perhaps one of the few times I use the "forced" marker !
without go-arounds; forced conversion to types I know with 100% certainty to be castable.
But let's leave the subject of type conversion/casting and move on to optional types, wrapping, and optional chaining, in general.
Generally, you should avoid force unwrapping unless you explicitly knows that the entity you unwrap will be non-nil. For general class properties, variables and so on, given that you state this question the way you do, I'll give your the following advice:
If you can use conditional unwrapping (
if-let
,guard-let
, nil coalescing operator??
), then don't use forced unwrapping (!
).
Below follows an example of the dangers of forced unwrapping. You can treat the first if
clause (if arc4random...
) as any smaller or larger segment of some program you've written with imperative programming techniques: we don't really know in detail just how 'name' will turn out until runtime, and our compiler can't really help us out here.
var name : String?
/* 'name' might or might not have a non-nil
value after this if clause */
if arc4random_uniform(2) < 1 {
name = "David"
}
/* Well-defined: us an if-let clause to try to unwrap your optional */
if let a = name {
print("Hello world "+a)
/* Very well-behaved, we did a safe
unwrap of 'name', if not nil, to constant a */
print("Hello world "+name!)
/* Well... In this scope, we know that name is,
for a fact, not nil. So here, a force unwrap
is ok (but not needed). */
}
let reallyGiveMeThatNameDammit = name!
/* NOT well-defined. We won't spot this at compile time, but
if 'name' is nil at runtime, we'll encounte a runtime error */
I recommend you to read up on optional chaining, a key subject in Swift.