检查“任何”值是不是为对象
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 是否是一个对象?”。不坚持使用is
或as?
,所以可能还有别的办法。
感谢@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
【讨论】:
以上是关于检查“任何”值是不是为对象的主要内容,如果未能解决你的问题,请参考以下文章