check if any property in an object is nil - Swift 3

后端 未结 3 2118
情深已故
情深已故 2021-01-06 16:24

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         


        
相关标签:
3条回答
  • 2021-01-06 16:56

    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.

    0 讨论(0)
  • 2021-01-06 17:00

    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})
        }
    }
    
    0 讨论(0)
  • 2021-01-06 17:14

    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
        }
    }
    
    0 讨论(0)
提交回复
热议问题