I'm fairly new to programming and I'm reading the Start Developing iOS Apps (Swift) programming guide. I understand that optionals have a question mark suffix which means the value could be nil or some other value. Apple's guide is walking us through how to use UIImagePickerController
and it's delegate. Apple uses the delegate method imagePickerControllerdidFinishPickingMediaWithInfo(_:)
which has a dictionary as a parameter.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
}
Apple's UIImagePickerControllerDelegate documentation doesn't list this parameter as optional nor is the UIImagePickerController
instance we created for this tutorial an optional however the tutorial states the following:
"This code accesses the original, unedited image from the info dictionary. It safely unwraps the optional returned by the dictionary and casts it as a UIImage object. The expectation is that the unwrapping and casting operations will never fail. If they do, it represents either a bug in your app that needs to be fixed at design time."
Does this mean that by using the guard keyword, it automatically turns the variable into an optional?
No. The optional value arises from the attempt to retrieve a value from a dictionary. Although the info
argument is a non-optional dictionary of type [String: Any]
, the subscript reference info[UIImagePickerControllerOriginalImage]
returns an optional value of type Any?
.
From The Swift Programming Language (Swift 3.0.1), "Accessing and Modifying a Dictionary":
Because it is possible to request a key for which no value exists, a dictionary’s subscript returns an optional value of the dictionary’s value type. If the dictionary contains a value for the requested key, the subscript returns an optional value containing the existing value for that key. Otherwise, the subscript returns
nil
:if let airportName = airports["DUB"] { print("The name of the airport is \(airportName).") } else { print("That airport is not in the airports dictionary.") } // Prints "The name of the airport is Dublin Airport."