check if any property in an object is nil - Swift

2019-02-11 05:16发布

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 {
var name : String?
var model: String?
var VIN: String?
}

let objCar = Vehicle()
objCar.name = "Volvo"

if objCar.{anyProperty} ! = nil {
//Go to other screen
}

Im in search of the {anyProperty} method where it returns true only if I have values for all properties of objCar. In our case, objCar has no model and VIN and so {anyProperty} is false and will come out of if loop

Pls advice

3条回答
狗以群分
2楼-- · 2019-02-11 05:35

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.

查看更多
神经病院院长
3楼-- · 2019-02-11 05:38

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
    }
}
查看更多
叼着烟拽天下
4楼-- · 2019-02-11 05:41

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})
    }
}
查看更多
登录 后发表回答