Im using Swift 3
Wondering whether any method is available to check if all the properties in an object has value / nil
Eg:
class Vehicle {
v
I'm not sure if this should be used for production apps, as I'm not very familiar with reflection in Swift (using Mirror
) and if it has any negative aspects (performance, etc).
Here goes:
class Vehicle {
var name : String?
var model: String?
var VIN: String?
}
let objCar = Vehicle()
objCar.name = "Volvo"
objCar.model = "242DL"
objCar.VIN = "123456"
let hasMissingValues = Mirror(reflecting: objCar).children.contains(where: {
if case Optional<Any>.some(_) = $0.value {
return false
} else {
return true
}
})
print(hasMissingValues)
hasMissingValues
will be false in the above example (all properties of Vehicle
are set). Comment the line where model
is set, for example, and the value of hasMissingValues
will now be true.
Note: There may be a better way to compare $0.value
(of type Any
) to nil. Also, this works for properties of any type (not just String
) of the class.
If you have a lot of fields, you can use this approach:
struct S {
let x: String?
let y: Int
let z: Bool
func hasNilField() -> Bool {
return ([x, y, z] as [Any?]).contains(where: { $0 == nil})
}
}
I would strongly recommend against this. State validation is something which should happen from inside a class. From inside the class, you should know better how to check validity.
class Vehicle {
var name: String?
var model: String?
var VIN: String?
func isReadyToAdvance() -> Bool {
return name != nil && model != nil && VIN != nil
}
}
let objCar = Vehicle()
objCar.name = "Volvo"
if objCar.isReadyToAdvance() {
// Go to other screen
}
If there are subclasses with different rules for isReadyToAdvance()
they can override that method.
If isReadyToAdvance()
doesn't make sense for the base class, then add it as an extension.
extension Vehicle {
func isReadyToAdvance() -> Bool {
return name != nil && model != nil && VIN != nil
}
}
@iPeter asked for something a bit more compact when there are lots of properties.
extension Vehicle {
func isReadyToAdvance() -> Bool {
// Add all the optional properties to optionals
let optionals: [Any?] = [name, model, VIN]
if (optionals.contains{ $0 == nil }) { return false }
// Any other checks
return true
}
}