rob rob - 4 months ago 8
Swift Question

How can I check if a property has been set using Swift reflection?

Some of my models have optional properties. I'm trying to write a method that can evaluate if they've been set.

Below is an attempt, but I can't figure out how to determine a nil value from an

Any
object [edit: (the
child
variable is of type
Any
)]. It doesn't compile.

func allPropertiesHaveValues(obj: AnyObject) -> Bool {
let mirror = Mirror(reflecting: obj)
for child in mirror.children {
let value = child.value
if let optionalValue = value as? AnyObject? { //Does not compile
if optionalValue == nil {
return false
}
}
}
return true
}





Edit:

I forgot to clarify that the
child
value in the above example is always of type
Any
. The
Any
type is difficult in that it cannot be compared to
nil
and a cast to
AnyObject
always fails. I've tried to illustrate it in the playground below.

var anyArray = [Any]();

var optionalStringWithValue: String? = "foo";
anyArray.append(optionalStringWithValue);

var nilOptional: String?
anyArray.append(nilOptional)

print(anyArray[0]); // "Optional("foo")\n"
print(anyArray[1]); // "nil\n"

if let optionalString = anyArray[0] as? AnyObject {
//will always fail
print("success")
}

//if anyArray[1] == nil { // will not compile

//}

rob rob
Answer

I used @ebluehands technique of reflecting the Any value to modify the original function. It cycles through the properties with an initial mirror, then reflects each one individually using displayStyle to determine if the property is optional.

func allPropertiesHaveValues(obj: AnyObject) -> Bool {
    let mirror = Mirror(reflecting: obj)
    for child in mirror.children {
        let value: Any = child.value
        let subMirror = Mirror(reflecting: value)
        if subMirror.displayStyle == .Optional {
            if subMirror.children.count == 0 {
                return false
            }
        }
    }
    return true
}