Swift allows us to use the shorthand notation str!
to unwrap an optional. But what if we want to do the opposite?
Say I have a variable:
var str = String() // String
Is there any shorthand notation to convert this to an optional (i.e. String?
or String!
)?
(E.g. I want to do something like var strOptional = ?(str)
.)
Alternatively, if there is no shorthand for this notation, how can I convert it to an optional without explicitly mentioning its type (e.g. I don't want to mention String
).
In other words, I know that I can wrap a variable as an optional with any of these methods:
var strOptional = str as String?
var strOptional: String? = str
var strOptional = String?(str)
... but in each case, I must explicitly write String
.
I would rather write something like: var strOptional = str as typeof?(str)
, if there is no shorthand syntax. (The advantage is that if the variable's type is frequently changed in the code base, it would be one less place to update.)
As far as a real world example of where this would be useful, imagine I want to use an AVCaptureDevice and I use the following code:
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
device.lockForConfiguration(nil)
lockForConfiguration()
will crash at runtime on a device that has no video camera, and the compiler won't warn me about it. The reason is that defaultDeviceWithMediaType
may return nil
according to the documentation[1], yet it is defined to return a AVCaptureDevice!
.
To fix a faulty API like this, it would be nice to do something like:
let device = ?(AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo))
... to get a AVCaptureDevice?
, and have the compiler catch any mistakes I might make.
Currently, I must resort to the more verbose:
let device: AVCaptureDevice? = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
Another example:
In this case, I want to give a default value to my variable that is a string, but later on, I may want to assign it a nil
value.
var myString = "Hi"
// ...
if (someCondition()) {
myString = nil // Syntax error: myString is String
}
Currently I have to resort to var myString: String? = "Hi"
but something like var myString = ?("Hi")
would be less verbose.
[1] If you open AVCaptureDevice.h, you will see the following documentation about the return value: "The default device with the given media type, or nil if no device with that media type exists."
If you defined a variable as optional, then to get the value from this variable, you will have to unwrap it. This just means putting an exclamation mark at the end of the variable. Optional("Hello, Swift 4!")
To use an optional, you "unwrap" it An optional String cannot be used in place of an actual String . To use the wrapped value inside an optional, you have to unwrap it. The simplest way to unwrap an optional is to add a ! after the optional name. This is called "force unwrapping".
A common way of unwrapping optionals is with if let syntax, which unwraps with a condition. If there was a value inside the optional then you can use it, but if there wasn't the condition fails. For example: if let unwrapped = name { print("\(unwrapped.
Optional is just an enum in swift, so you can do: Optional(str)
From the swift interface:
/// A type that can represent either a `Wrapped` value or `nil`, the absence
/// of a value.
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
/// Construct a `nil` instance.
public init()
/// Construct a non-`nil` instance that stores `some`.
public init(_ some: Wrapped)
/// If `self == nil`, returns `nil`. Otherwise, returns `f(self!)`.
@warn_unused_result
public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
/// Returns `nil` if `self` is `nil`, `f(self!)` otherwise.
@warn_unused_result
public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
/// Create an instance initialized with `nil`.
public init(nilLiteral: ())
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With