为什么compactMap无法移除Mirror生成的[Any?]数组中的nil值?
问题根源
Mirror.Child.value的返回类型是Any,你将其映射为[Any?]时,相当于给所有元素额外包了一层Optional。如果元素本身就是Optional类型(比如你的代码里的optionalString、optionalInt),就会形成两层嵌套的Optional(即Any??)。
compactMap默认只会解开最外层的Optional,此时最外层Optional永远有值(哪怕内部包装的是.none),所以不会触发过滤逻辑,nil也就保留了下来。
你后面两个测试用例能正常生效,是因为直接构造的[Any?]只有一层Optional,compactMap可以正常识别并过滤nil。
解决方案
写一个递归解包任意嵌套Optional的辅助方法,再配合compactMap使用即可:
// 递归解开任意层级的Optional包装,为nil则返回nil func unwrap(any: Any) -> Any? { let mirror = Mirror(reflecting: any) // 非Optional类型直接返回原值 guard mirror.displayStyle == .optional else { return any } // Optional为空的情况返回nil guard let firstChild = mirror.children.first else { return nil } // 递归解开内层可能存在的嵌套Optional return unwrap(any: firstChild.value) } // 原逻辑修改为 let compactArrayOfChildrenValues: [Any] = arrayOfChildrenValues.compactMap { unwrap(any: $0) }
修改后打印结果就是你预期的["a", "b", "c"]。
内容的提问来源于stack exchange,提问作者swiftPunk
相关产品推荐
相关产品推荐

