如何在swift中检查`Any(not Any?)`是否为nil

时间:2018-05-09 13:29:16

标签: swift

我在swift中使用Mirror,我发现Mirror.Child非常奇怪,标签可以为空,但值似乎不可为空。

public typealias Child = (label: String?, value: Any)

我不知道如何检查该值是否为零。

let b: Bool? = true
let a: Any = b
print(a == nil) // false

我有一个解决方案:

print(String(describing: a) == "nil") // true

但这显然不是一个好的解决方案。

检查a是否为零的最佳方式是什么?

让我详细说明一下,

let mirror = Mirror(reflecting: object) // object can be any object.
for child in mirror.children {
    guard let label = child.label else {
        continue
    }
    // how to check if the value is nil or not here ?
    setValue(child.value, forKey: label)
}

2 个答案:

答案 0 :(得分:10)

使用if case

您可以使用if case Optional<Any>.none = a来测试a是否nil

var b: Bool?
var a = b as Any
if case Optional<Any>.none = a {
    print("nil")
} else {
    print("not nil")
}
  
nil
  
b = true
a = b as Any
if case Optional<Any>.none = a {
    print("nil")
} else {
    print("not nil")
}
  
not nil
  

使用switch

您也可以将模式测试与switch一起使用:

var b: Bool?
var a = b as Any

switch a {
case Optional<Any>.none:
    print("nil")
default:
    print("not nil")
}
  
nil
  

答案 1 :(得分:0)

我发现Mirror.Child非常奇怪,标签可以为空,但是 值似乎不能为空。

labelnil时,您可能在数组内,其中的标签不存在。

我不知道如何检查该值是否为零。

要检查Any是否为Optional,您可以实施以下方法:

extension Optional {
    static func isNil(_ object: Wrapped) -> Bool {
        switch object as Any {
        case Optional<Any>.none:
            return true
        default:
            return false
        }
    }
}

示例用法:

let a: Bool? = nil
let b: Bool? = true
print(Optional.isNil(a)) // prints 'true'
print(Optional.isNil(b)) // prints 'false'

上述代码的更详细示例如下:

enum ContentType {
    case value   // single value object
    case array   // object is an array
    case object  // object is a structure
}

func getType(from mirror: Mirror) -> ContentType {
    // if there are no children, we are probably a single value
    if mirror.children.count == 0 {
        return .value
    }
    if mirror.children.first?.label == nil {
        // its probably an array
        return .array
    }
    // everything else is an object (dictionary)
    return .object
}

func formArray(from mirror: Mirror) -> [(index: Int, value: Any)] {
    var startIndex = mirror.children.startIndex
    var array: [(index: Int, value: Any)] = []
    for index in 0..<mirror.children.count {
        let child = mirror.children[startIndex]
        startIndex = mirror.children.index(after: startIndex)
        array.append((index: index, value: child.value))
    }
    return array
}

func formObjects(from mirror: Mirror) -> [(label: String, value: Any)] {
    let objects: [(label: String, value: Any)] =
        mirror.children.map { (label: $0.label ?? "", value: $0.value) }
    return objects
}

func checkObject(_ object: Any) {
    let mirror = Mirror(reflecting: object) // object can be any object.
    let objectType = getType(from: mirror)
    switch objectType {
    case .value:
        print("value: \(object)")
    case .array:
        let array = formArray(from: mirror)
        for element in array {
            let isNil = Optional.isNil(element.value)
            print("Index \(element.index) is \(element.value), the value \(isNil ? "is" : "is not") nil.")
        }
    case .object:
        let objects = formObjects(from: mirror)
        for element in objects {
            let isNil = Optional.isNil(element.value)
            print("\(element.label) is \(element.value), the value \(isNil ? "is" : "is not") nil.")
        }
    }
}

struct Test {
    let text: String?
    let number: Int
}

let object = Test(text: nil, number: 42)
checkObject(object)
//text is nil, the value is nil.
//number is 42, the value is not nil.

let array = [1, 2, 3]
checkObject(array)
//Index 0 is 1, the value is not nil.
//Index 1 is 2, the value is not nil.
//Index 2 is 3, the value is not nil.

let arrayWithOptionals = [1, nil, 3]
checkObject(arrayWithOptionals)
//Index 0 is Optional(1), the value is not nil.
//Index 1 is nil, the value is nil.
//Index 2 is Optional(3), the value is not nil.

这应该可以解决您的问题。