Optionals are an integral aspect of Swift. Optional types are used to represent the absence or presence of a value. In other words, an optional type can hold either a value or nil
, which indicates that a value is absent. When you declare a variable as optional, you tell the Swift compiler that the variable may not always have a value.
To work with the actual value contained in an optional, you must unwrap it to access the underlying value. That brings us to the error you are seeing.
value of optional type URL?' must be unwrapped to a value of type URL
The compiler tells you that you try to use an optional value without unwrapping it first to access the underlying value. Let's look at an example to better understand the issue and how to resolve it. Create a playground in Xcode if you'd like to follow along with me. Add an import statement for the Foundation framework at the top. Define a constant urlAsString
that stores a URL as a string.
import Foundation
let urlAsString = "https://cocoacasts.com/"
We pass the value stored in urlAsString
to one of the initializers of the URL
struct to create a URL
object. The initializer is failable so the url
constant is of type URL?
. That is important to understand. If the value stored in urlAsString
isn't a valid URL, then the initialization of the URL
object fails.
import Foundation
let urlAsString = "https://cocoacasts.com/"
let url = URL(string: urlAsString)
Let's use the URL
object to create a URLRequest
object. We pass the value stored in the url
constant to one of the initializers of the URLRequest
struct. The result is a compile-time error. The compiler notifies us that the url
constant is of type URL?
, an optional type. The initializer of the URLRequest
struct expects a URL
object, not an optional URL
object.
import Foundation
let urlAsString = "https://cocoacasts.com/"
let url = URL(string: urlAsString)
let request = URLRequest(url: url)
The solution is simple, though. We use optional binding to safely access the value stored in the URL
constant. In other words, we safely check if the optional contains a value. If it does, then we can use that value to create a URLRequest
object. If it doesn't, we print a message to the console.
import Foundation
let urlAsString = "https://cocoacasts.com/"
let url = URL(string: urlAsString)
if let url {
let request = URLRequest(url: url)
} else {
print("Invalid URL")
}
You could force unwrap the optional using the exclamation mark, but that isn't something I recommend. Force unwrapping should be done very, very sparingly. Why is that? If you force unwrap an optional that doesn't contain a value, a fatal error is thrown and the process terminates immediately. This simply means that your app crashes.
There are valid use cases for using the exclamation mark to force unwrap optionals, but decide for yourself in advance what those use cases are. Understand the risk involved and stick to those use cases. That is the approach I recommend.