检查“任何”值是不是为对象

Posted

技术标签:

【中文标题】检查“任何”值是不是为对象【英文标题】:Check if `Any` value is object检查“任何”值是否为对象 【发布时间】:2016-08-27 19:25:46 【问题描述】:

我惊讶地发现这个条件总是成立的:

let foo: Any = 4
if let object = foo as? AnyObject 
    print("It's an object.")
    //do something with `object` that requires reference semantics
 else 
    print("It's not an object.")

看来不管foo原来是什么类型,都转换成对应类的实例了。有没有可靠的方法来确定foo 是否是一个对象?

【问题讨论】:

这是在 Swift 3 中吗?如果是这样,请参阅AnyObject not working in Xcode8 beta6? 链接的线程没有回答“如果Any是类实例或其他东西,我们如何区分它的内容?”的问题。为什么这被标记为“重复”? @MartinR,OP 的描述是“是否有可靠的方法来确定 foo 是否是一个对象?”。不坚持使用isas?,所以可能还有别的办法。 感谢@Hamish 的链接;很高兴知道我不是唯一一个对这种行为感到惊讶的人。 【参考方案1】:

更新

我在下面显示的代码被报告为在发布版本中不起作用。 (请参阅下面 Paul Cantrell 的评论。)

为我的“就我所测试的”道歉太有限了。

当我找到有关此的更多信息时,我会更新此答案。


我不确定我们能否在下一个 beta(或 GM 或 Released 版本...)中看到这种行为,但这在 Xcode 8 beta 6 中可以正常工作。

let foo: Any = 4
if type(of: foo) is AnyClass 
    print("It's an object.")
    let object = foo as AnyObject
    //do something with `object` that requires reference semantics
 else 
    print("It's not an object.") //->It's not an object.


class MyClass 
let bar: Any = MyClass()
if type(of: bar) is AnyClass 
    print("It's an object.") //->It's an object.
    let object = foo as AnyObject
    //do something with `object` that requires reference semantics
 else 
    print("It's not an object.")


let baz: Any = Array<AnyObject>()
if type(of: baz) is AnyClass 
    print("It's an object.")
    let object = foo as AnyObject
    //do something with `object` that requires reference semantics
 else 
    print("It's not an object.") //->It's not an object.

我无法检查所有可能的情况,因此可能有一些边缘情况不起作用。但据我测试,这似乎按预期工作。

【讨论】:

请注意,从 Swift 3.0 开始,当采用存在类型时,这会破坏优化的发布版本:bugs.swift.org/browse/SR-2867 @PaulCantrell,感谢您的报告。我会更新我的答案,包括该信息。 这在 Xcode 8.3.3 中运行没有问题,包括调试和发布版本。【参考方案2】:

也许您想查看Mirror,它可以进行一定程度的内省。文档是here

import Foundation

func prettyPrint(_ any: Any) -> String 
    let m = Mirror(reflecting: any)
    switch m.displayStyle 
    case .some(.class): // ****
        return "Class"
    case .some(.collection):
        return "Collection, \(m.children.count) elements"
    case .some(.tuple):
        return "Tuple, \(m.children.count) elements"
    case .some(.dictionary):
        return "Dictionary, \(m.children.count) elements"
    case .some(.set):
        return "Set, \(m.children.count) elements"
    case .some(.optional):
        return "Optional"
    case .some(.enum):
        return "Enum"
    case .some(.struct):
        return "Struct"
    default:
        return "\(String(describing: m.displayStyle))"
    

class A 

prettyPrint([1, 2, 3]) // "Collection, 3 elements"
prettyPrint(Set<String>()) // "Set, 0 elements"
prettyPrint([1: 2, 3: 4]) // "Dictionary, 2 elements"
prettyPrint((1, 2, 3)) // "Tuple, 3 elements"
prettyPrint(3) // "nil"
prettyPrint("3") // "nil"
prettyPrint(NSObject()) // "Class"
prettyPrint(NSArray(array:[1, 2, 3])) // "Collection, 3 elements"
prettyPrint(A()) // "Class"

// prettyPrint(nil) // Compile time error "Nil is not compatible with Any

【讨论】:

以上是关于检查“任何”值是不是为对象的主要内容,如果未能解决你的问题,请参考以下文章

如何快速检查对象数组中是不是存在属性值

lodash 检查对象属性是不是有值

Vue/JS - 检查两个对象的所有值是不是为空

检查数组对象中特定索引的所有值是不是为 Null?

检查对象中的值是不是为空或空javascript

检查对象是不是为值类型的最有效方法