Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shorthand for wrapping a swift variable in an optional?

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."

like image 511
Senseful Avatar asked Apr 20 '15 21:04

Senseful


People also ask

How do you indicate that this variable is optional Swift?

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!")

How do I make a value optional in Swift?

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".

What should we use for unwrapping value inside optional?

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.


1 Answers

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: ())
}
like image 54
icecrystal23 Avatar answered Sep 25 '22 06:09

icecrystal23