Hi guys in Swift community, this is my first topic in this community, I want to discuss the way to unwrap an Any object to a runtime optional type.
class Test {
var biz: Int64? = 0xFF0000
}
let a: Int8? = nil
let b: Test? = Test()
let aa = a as Any
let bb = b as Any
// questions start from here, now we have 2 `Any` objs, lets figure out whether it is nil.
for p in [aa, bb] {
print(p == nil ? "NIL" : "Non Nil")
}
I see the compiler warns me that this comparison always fails. And after some investigation, found that Any is a wrapper, so the wrapper is not nil of course.
Code I want to achieve:
class Test {
var biz: Int64? = 0xFF0000
}
let a: Int8? = nil
let b: Test? = Test()
let aa = a as Any
let bb = b as Any
let values = [aa, bb]
let types = [Int8.self, Test.self]
for i in 0...2 {
print((values[i] as? types[i]) == nil ? "NIL" : "Non Nil") // as? requires a compile time type, not runtime.
}
The reason I want to distinguish Any from nil withou compile time type is that I want to use this API.
AnyReturn swift_reflectionMirror_subscript(OpaqueValue *value, const Metadata *type,
intptr_t index,
const char **outName,
void (**outFreeFunc)(const char *),
const Metadata *T)
Value was wrapped in Any and I'm trying to reverse the way used by this function to wrap value to get the concrete value is nil or not. To be more specific, in EnumImpl
's AnyReturn subscript(intptr_t i, const char **outName, void (**outFreeFunc)(const char *))
function, raw value was wrapped to Any, I want to unwrap Any to raw value conversely.
The question is, is there any better way to unwrap an Any to an Optional in runtime without compile-time type?
Example application scene:
struct Body {
let weight: Int?
let height: Int?
}
class Person {
let name: String?
let body: Body? = Body()
}
@_silgen_name("swift_reflectionMirror_subscript")
internal func _getChild<T>(
of: T,
type: Any.Type,
index: Int,
outName: UnsafeMutablePointer<UnsafePointer<CChar>?>,
outFreeFunc: UnsafeMutablePointer<NameFreeFunc?>
) -> Any
func getSubStructure(obj: Any) -> [Any] {
var res = [Any]()
for i in 0...1 {
let child = _getChild(of: obj,
type: type(of: obj),
index: i,
outName: name,//ignore decl
outFreeFunc: func//ignore decl
)
res.append(child)
}
return res
}
let subStructure = getSubStructure(Person())
now, how to determine subStructure[0] is nil, and subStructure[1] isn't nil with a generic function? I have to use this function to handle all types that may appear in my app, I can't just write subStructure[0] as? XX
, I want a runtime type coercion here.
Thanks, best wishes,
Yifan