I want to convert a type defined as RealmOptional
to either Int
or Float
, depending on the type assigned to the generic. However, when I tried distributing them using switch
statement, it turned out that not RealmOptional<Int>()
but RealmOptional<Float>()
were classified to Int
cases. For example,
switch value { // value is of type AnyObject?
case is String:
cell.valueLabel.text = value as? String
case is Int:
// RealmOptional<Float> are executed here
let v = value as! Int
cell.valueLabel.text = String(v) // Float is now treated as Int
case is Double:
print("double") // not printed at all
cell.valueLabel.text = String(value!)
default:
break
}
Why does RealmOptional<Float>()
behave as Int
here? And how can I set the text to the value
correctly?
Lets assume your RealmOptional<Float>()
variable is named myFloat
. Then, use the getter for the RealmOptional:s (see this git entry for Realm) underlying value, .value
, rather then checking the RealmOptional itself:
var value = myFloat.value // value variable now of type Float
Below follows and explanation of why the AnyObject?
switches doesn't behave as you expect:
From Apples Language Guide - Type Casting:
Type Casting for Any and AnyObject
Swift provides two special type aliases for working with non-specific types:
- AnyObject can represent an instance of any class type.
- Any can represent an instance of any type at all, including function types.
Hence, the AnyObject
type can can hold instances of any class type, but the fundamental numeric types (Int
, Double
etc) in Swift are not of class type, but of structure type.
In the switch
in your example, the AnyObject
instance is not inferred but cast to the first possible successful downcast, which will be whatever case
you put top-most that is of a numeric type. Hence, if you change the ordering of your case
:s in the switch, the casting will change.
let value: AnyObject? = 30.0
// try change the order
switch value {
case is String: print("string");
case is Float: print("float"); // hits `Float` downcast first -> prints float
case is Int: print("int");
default: print("other")
}
Now, you could, however, cast your AnyObject
to an NSNumber
(class instance), and continue from there. From Working with Cocoa Data Types documentation:
Instances of the Swift numeric structure types, such as Int, UInt, Float, Double, and Bool, cannot be represented by the AnyObject type, because AnyObject only represents instances of a class type. However, when bridging to Foundation is enabled, Swift numeric values can be assigned to constants and variables of AnyObject type as bridged instances of the NSNumber class.
Note however that NSNumber
is fundamentally different from the Swift numeric types (Int
, Double
etc) in that the former hold any kind of number, and allows us to cast this number to different type of numeric types. However, we cannot easily infer which type a specific NSNumber
instance should be cast to, but we could implement our own (not so pretty) specification as how to infer different NSNumber
to different swift fundamental numeric types.
However, before proceeding with NSNumber
hacking:
From above, the core problem is that your value
property is of type AnyObject?
. Could you please post the code that lead to value
being of type AnyObject?
. Possibly the casting to Int
, Float
and so on if not necessary if using the getter of the RealmOptional (hence no need to casting RealmOptional<T>()
to AnyObject?
?).
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