我正在使用 Contacts 框架,我有循环遍历 CNContact 的所有值的代码,并执行以下操作:
if let label = value as? CNLabeledValue<CNPhoneNumber> {
let v: CNPhoneNumber = label.value
NSLog("v = \(v), type = \(type(of: v))")
}
大多数情况下,它会像这样打印输出:
v = <CNPhoneNumber: 0x1234567890a0: countryCode=us, digits=7775551212>, type = CNPhoneNumber
但它也会像这样打印输出:
v = foo@example.com, type = __NSCFString
不过,在我尝试过的其他情况下,占位符类型作为类型的一部分是相关的:
Welcome to Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1). Type :help for assistance.
1> class C<T> { }
2> let c1 = C<Int>()
c1: C<Int> = {}
3> let c2 = C<String>()
c2: C<String> = {}
4> c1 as? C<String>
$R0: C<String>? = nil
这里的规则是什么?为什么 CNLabeledValue<NSString>
在这里成功转换为 CNLabeledValue<CNPhoneNumber>
?那么如何准确检测这种类型呢?
编辑:这是一个完整的程序:
import Cocoa
import Contacts
let me = try! CNContactStore().unifiedMeContactWithKeys(toFetch: [CNContactEmailAddressesKey as NSString])
let value = me.value(forKey: CNContactEmailAddressesKey)
if let array = value as? [CNLabeledValue<CNPhoneNumber>] {
for item in array {
if let phone = item as? CNLabeledValue<CNPhoneNumber> {
let v: CNPhoneNumber = phone.value
NSLog("v = \(v), type = \(type(of: v))")
}
}
}
最佳答案
CNLabeledValue
是一个 Objective-C 类。 Objective-C 没有真正的泛型。当 Swift 出现时,引入了所谓的“轻量级泛型”以提高与 Swift 的互操作性。这些只会帮助编译器进行类型检查,但在运行时会丢失额外的类型信息(基本上是 type erasure )。这就是为什么您在第一个示例中得到任何类型的原因。
在您的第二个示例中,您定义了真正的 Swift 泛型。那里的类型不会被删除,因此它们在运行时可用,并且可以实际检查类型。
关于swift - 为什么将 A<B> 转换为 A<C> 有时会成功,即使 B 和 C 无关?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41880826/