向下转换“Any”时出现快速错误

问题描述 投票:0回答:2

以下代码几乎是来自 Apple 文档的精确复制品,并且编译时没有错误:

guard let firstItem = (rawItems! as? Array<Dictionary<String, Any>>)?.first else {
    throw AnError()
}

let identityRef = firstItem[kSecImportItemIdentity as String] 
               as! SecIdentity?   // !!!

guard let identity = identityRef else {
    throw AnError()
}

标有

!!!
的行包含强制向下转换,而用
as!
替换
as
显然会导致编译错误
'Any?' is not convertible to 'SecIdentity?'...
确实
SecIdentity
是一个类,而
Any
甚至可能不是一个类。

我实在无法解释的是以下内容。如果我尝试使用这个来使代码更安全

guard let idenity = firstItem[kSecImportItemIdentity as String] as? SecIdentity
else {
    throw AnError()
}

或者这个

guard let idenityRef = firstItem[kSecImportItemIdentity as String] as? SecIdentity?
else {
    throw AnError()
}

我收到编译错误:

Conditional downcast to CoreFoundation type 'SecIdentity' will always succeed

swift downcast optional-values
2个回答
8
投票

SecIdentity
“代表身份的抽象 Core Foundation 类型对象” 并且 Core Foundation 类型的类型可以是 用
CFGetTypeID()
检查。所以你可以先检查类型ID。如果它与某个类型的 ID 匹配
SecIdentity
那么强制施法就安全了:

guard let cfIdentity = firstItem[kSecImportItemIdentity as String] as CFTypeRef?,
    CFGetTypeID(cfIdentity) == SecIdentityGetTypeID() else {
        throw AnError()
}
let identity = cfIdentity as! SecIdentity

另请参阅错误报告 SR-7015 CoreFoundation 条件向下转型诊断并没有应有的帮助

应使用一条消息更新诊断,通知开发人员比较 CFTypeId(如果可能,使用修复程序)。


3
投票

CoreFoundation 类型的行为与 Foundation 类型略有不同。

不要有条件地贬低身份。如果可选绑定成功,您可以强制解开身份

guard let identity = firstItem[kSecImportItemIdentity as String] else { throw AnError() }
var privateKey : SecKey?
let status = SecIdentityCopyPrivateKey(identity as! SecIdentity, &privateKey)

旁注:

请不要写

as? SecIdentity?

要么是有条件的向下转型
as? SecIdentity
,要么是桥接转型可选的
as SecIdentity?

© www.soinside.com 2019 - 2024. All rights reserved.