How do I cast an Any value with nil in it to a Any?
To simply check for nil
content in the property value wrapped in an Any
, you can, contrary to methods described in the other answers, actually work your way around casting/binding/checking to a concrete non-Any
type by directly applying pattern matching to Optional<Any>.none
or Optional<Any>.some(...)
.
Example setup (different members types: we don't want to annotate all these different types simply for reflection checking for nil
content)
struct MyStruct {
let myString: String?
let myInt: Int?
let myDouble: Double?
// ...
init(_ myString: String?, _ myInt: Int?, _ myDouble: Double?) {
self.myString = myString
self.myInt = myInt
self.myDouble = myDouble
}
}
Simple logging: Extracting property names of nil
valued properties
Pattern matching to Optional<Any>.none
, if you simply want to log info on nil
valued entities:
for case (let label as String, Optional<Any>.none) in
Mirror(reflecting: MyStruct("foo", nil, 4.2)).children {
print("property \(label) is nil")
}
/* property myInt is nil */
Slightly more detailed logging: for nil
as well as non-nil
valued properties
Pattern matching to Optional<Any>.some(...)
, in case you want more detailed logging (the binded x
value below corresponds to your guaranteed non-nil
Any
instance)
for property in Mirror(reflecting: MyStruct("foo", nil, 4.2)).children {
if let label = property.label {
if case Optional<Any>.some(let x) = property.value {
print("property \(label) is not nil (value: \(x))")
}
else {
print("property \(label) is nil")
}
}
}
/* property myString is not nil (value: foo)
property myInt is nil
property myDouble is not nil (value: 4.2) */
Or, the latter using a switch
case instead:
for property in Mirror(reflecting: MyStruct("foo", nil, 4.2)).children {
switch(property) {
case (let label as String, Optional<Any>.some(let x)):
print("property \(label) is not nil (value: \(x))")
case (let label as String, _): print("property \(label) is nil")
default: ()
}
}
/* property myString is not nil (value: foo)
property myInt is nil
property myDouble is not nil (value: 4.2) */
How to cast nil interface to nil other interface
Does this work?
func preferredWay(i interface{}) error {
k, _ := i.(error)
return k
}
Is it possible to cast Any to an Optional?
For Swift 2.0, you can use the following:
let x: Int? = 10
let y: Any = x
let z = Mirror(reflecting: y).descendant("Some") as? Int
Or as a function:
func castToOptional<T>(x: Any) -> T? {
return Mirror(reflecting: x).descendant("Some") as? T
}
let x: Int? = 10
let y: Any = x
let z: Int? = castToOptional(y)
Or you can do this if you don't like Reflection:
func castToOptional<T>(x: Any) -> T {
return x as! T
}
let x: Int? = 10
let y: Any = x
let z: Int? = castToOptional(y)
Swift: Cast Any Object to Int64 = nil
In
let dict : [String : AnyObject] = ["intValue": 1234, "stringValue" : "some text"]
the number 1234
is stored as an NSNumber
object, and that can
be cast to Int
, UInt
, Float
, ..., but not to the fixed
size integer types like Int64
.
To retrieve a 64-bit value even on 32-bit platforms, you have to
go via NSNumber
explicitly:
if let val = dict["intValue"] as? NSNumber {
let int64value = val.longLongValue // This is an `Int64`
print(int64value)
}
Swift nil Any != nil
Think of Any
and Optional<Wrapped>
like boxes.
Any
is an opaque box that can hold anything. You can gleam what's inside by trying to cast it usingas?
.Optional<Wrapped>
is a transparent box. It lets you see that its contents are either a value ofOptional<Wrapped>.some(wrapped)
orOptional<Wrapped>.none()
.
An Optional<Any>
and Any
containing an Optional<Wrapped>
aren't the same thing.
1. x
is a value of Optional<Any>.none
, a.k.a. nil
. nil
gets printed, so that makes sense.
2. type(of: x)
is the type of x
, Optional<Any>
, as we expected.
3. x == nil
is calling an ==
operator of type (T, T) -> Bool
. Since both args need to be the same type, and since x
has a value of Optional<Any>.none
(of type Optional<Any>
), nil
is inferred to be Optional<Any>.none
. The two are equivalent, so we get true
, as expected.
4. y
is a value of type Any
. At compile time, nothing more is known about y
. It just so happens that the value behind hidden by the opaque curtain of Any
is x
. print
is implemented to "see through" Any
instances
, to show you what's really there.
5. type(of: y)
is doing something similar to print
. It's using runtime type information to see exactly what the runtime value stored into y
is. The static type of y
is Any
, but type(of: y)
shows us that the runtime type of its value is Optional<Any>
.
6. y == nil
This is where it gets a little trickier.
The choice of which overload of a function or operator to call is done at compile time, based on the statically known types of the operands. That is to say, operators and functions aren't dynamically dispatched based on the types of their arguments, the way they're dynamically dispatched based on the type of their objects (e.g. the foo
in foo.bar()
).
The overload that's selected here is ==(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool
. You can see its implementation on lines 449-481 of Optional.swift
.
Its left-hand-side operand is Wrapped?
, a.k.a. an Optional<Wrapped>
.
Its right-hand-side operand is _OptionalNilComparisonType
. This is a special type that conforms to ExpressibleByNilLiteral
.
Optional is one type that conforms to ExpressibleByNilLiteral
, meaning that you can write let x: Optional<Int> = nil
, and the compiler could use that protocol to understand that nil
should mean Optional<Int>.none
. The ExpressibleByNilLiteral
protocol exists to allow this behaviour to be extensible by other types. For example, you can imagine a Python interopability framework, where you would want to be able to say let none: PyObject = nil
, which could be passed into Python
and resolve to None
, Python's null type.
What's happening here is that the left hand side (y
, of type Any
), is being promoted to type Any?
. The promoted value has type Optional<Any>.some(old_value_of_y)
. The right hand side, the nil
, is being used to instantiate a value of _OptionalNilComparisonType
, equivalent to calling _OptionalNilComparisonType.init(nilLiteral: ())
.
Thus, your call site is equivalent to:
Optional<Any>.some((Optional<Any>.none) as Any) == _OptionalNilComparisonType(nilLiteral: ()) /*
↑ ↑↖︎_the value of x_↗︎ ↑↑
↑ ↖︎_the value of y _________↗︎↑
↖︎_the value of y after promotion to optional__↗︎ */
According to the implementation, the left side is a some
, the right side is a nil
, and thus they're unequal.
You might say:
Well this is pretty non-obvious behaviour, it's not what I wanted.
To which I would respond:
Don't ignore the compiler errors, they're right on point:
warning: comparing non-optional value of type
Any
tonil
always returnsfalse
Implicit Any? to Any cast warning when passing Any? type variable in as Any? type parameter
Dictionary look ups return optional values because the key might not exist. In the case of a non-existent key, the look up returns nil
, so the type of the dictionary look up has to be optional.
In your case, your values are of type Any?
, so a look up from that dictionary returns a doubly wrapped optional Any??
. So you are trying to pass a value of type Any??
to a function that takes Any?
.
If you use optional binding to handle and unwrap the dictionary access, everything works:
let testDict : Dictionary<String, Any?> = ["Test": "Hello"];
if let value = testDict["Test"] {
// "Test" key is valid
someFunc(value);
}
Related Topics
Wkwebview: How to Handle Blob Url
Swiftui Present Alert with Input Field
Swift Performseguewithidentifier Shows Black Screen
Why Swift Throws Error When Using Optional Param in Closure Func
Incorrect String to Date Conversion Swift 3.0
Perform Segue from Another Class with Helper Function
Is There a Preferred Technique to Prohibit Pasting into a Uitextfield
How to Cast an Any Value with Nil in It to a Any
Many Ways of Defining a Swift Dictionary
Toggle Selection in a List - Swiftui
Calling a Function Defined in Assembly from Swift
Get Lat and Long from Tapped Overlay in Google Maps
Nothing Prints Out in the Console in Command Line Tool Xcode
Get Fullpath or Convert to Fullpath
Create View Based Nstableview Programmatically Using Bindings in Swift