Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if variable is an Optional, and what type it wraps

Tags:

swift

Is it possible to check if a variable is an optional, and what type is it wrapping?

It is possible to check if a variable is an specific optional:

let someString: String? = "oneString"
var anyThing: Any = someString

anyThing.dynamicType // Swift.Optional<Swift.String>
anyThing.dynamicType is Optional<String>.Type // true
anyThing.dynamicType is Optional<UIView>.Type // false

But is it possible to check agains any type of optional? Something like:

anyThing.dynamicType is Optional.Type // fails since T cant be inferred
// or 
anyThing.dynamicType is Optional<Any>.Type // false

And once knowing you have an optional, retrieve the type it is wrapping:

// hypothetical code 
anyThing.optionalType // returns String.Type
like image 442
Maic López Sáenz Avatar asked Sep 18 '15 06:09

Maic López Sáenz


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

What is optional variable?

An optional in Swift is basically a constant or variable that can hold a value OR no value. The value can or cannot be nil. It is denoted by appending a “?” after the type declaration. For example: var tweet: String?

What is the type of optional in Swift?

An optional acts as a container for a value of a particular type. The container holds a value or it doesn't. Type safety is a cornerstone of the Swift language. As a result, variables and constants need to be initialized before they can be accessed.


2 Answers

Since a protocol can be created as means of a typeless Optional the same protocol can be used to provide access to the optional type. Example is in Swift 2, although it should work similarly in previous versions:

protocol OptionalProtocol {
    func wrappedType() -> Any.Type
}

extension Optional : OptionalProtocol {
    func wrappedType() -> Any.Type {
        return Wrapped.self
    }
}

let maybeInt: Any = Optional<Int>.Some(12)
let maybeString: Any = Optional<String>.Some("maybe")

if let optional = maybeInt as? OptionalProtocol {
    print(optional.wrappedType()) // Int
    optional.wrappedType() is Int.Type // true
}

if let optional = maybeString as? OptionalProtocol {
    print(optional.wrappedType()) // String
    optional.wrappedType() is String.Type // true
}

The protocol can even be used to check and unwrap the contained optional value

like image 64
Maic López Sáenz Avatar answered Oct 16 '22 17:10

Maic López Sáenz


With Swift2.0:

let someString: String? = "oneString"
var anyThing: Any = someString

// is `Optional`
Mirror(reflecting: anyThing).displayStyle == .Optional // -> true

But extracting wrapped type is not so easy.

You could:

anyThing.dynamicType // -> Optional<String>.Type (as Any.Type)
Mirror(reflecting: anyThing).subjectType // -> Optional<String>.Type (as Any.Type)

But I don't know how to extract String.Type from Optional<String>.Type wrapped with Any.Type

like image 45
rintaro Avatar answered Oct 16 '22 17:10

rintaro