Why would you create a \"Implicitly Unwrapped Optional\" vs creating just a regular variable or constant? If you know that it can be successfully unwrapped then why create a
Consider the case of an object that may have nil properties while it's being constructed and configured, but is immutable and non-nil afterwards (NSImage is often treated this way, though in its case it's still useful to mutate sometimes). Implicitly unwrapped optionals would clean up its code a good deal, with relatively low loss of safety (as long as the one guarantee held, it would be safe).
(Edit) To be clear though: regular optionals are nearly always preferable.
If you know for sure, a value return from an optional instead of nil
, Implicitly Unwrapped Optionals use to directly catch those values from optionals and non optionals can't.
//Optional string with a value
let optionalString: String? = "This is an optional String"
//Declaration of an Implicitly Unwrapped Optional String
let implicitlyUnwrappedOptionalString: String!
//Declaration of a non Optional String
let nonOptionalString: String
//Here you can catch the value of an optional
implicitlyUnwrappedOptionalString = optionalString
//Here you can't catch the value of an optional and this will cause an error
nonOptionalString = optionalString
So this is the difference between use of
let someString : String!
and let someString : String
Apple gives a great example in The Swift Programming Language -> Automatic Reference Counting -> Resolving Strong Reference Cycles Between Class Instances -> Unowned References and Implicitly Unwrapped Optional Properties
class Country {
let name: String
var capitalCity: City! // Apple finally correct this line until 2.0 Prerelease (let -> var)
init(name: String, capitalName: String) {
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
}
class City {
let name: String
unowned let country: Country
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
The initializer for
City
is called from within the initializer forCountry
. However, the initializer forCountry
cannot passself
to theCity
initializer until a newCountry
instance is fully initialized, as described in Two-Phase Initialization.To cope with this requirement, you declare the
capitalCity
property ofCountry
as an implicitly unwrapped optional property.
The rationale of implicit optionals is easier to explain by first looking at the rationale for forced unwrapping.
Forced unwrapping of an optional (implicit or not), using the ! operator, means you're certain that your code has no bugs and the optional already has a value where it is being unwrapped. Without the ! operator, you would probably just assert with an optional binding:
if let value = optionalWhichTotallyHasAValue {
println("\(value)")
} else {
assert(false)
}
which is not as nice as
println("\(value!)")
Now, implicit optionals let you express having an optional which you expect to always to have a value when unwrapped, in all possible flows. So it just goes a step further in helping you - by relaxing the requirement of writing the ! to unwrap each time, and ensuring that the runtime will still error in case your assumptions about the flow are wrong.