向下转换“任何”时出现 Swift 错误

Posted

技术标签:

【中文标题】向下转换“任何”时出现 Swift 错误【英文标题】:Swift error while downcasting 'Any' 【发布时间】:2018-08-12 04:01:11 【问题描述】:

以下代码与Apple Documentation 几乎完全相同,并且编译时没有错误:

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

【问题讨论】:

您是否收到 both guards 的 Conditional downcast... 编译错误?--即使是第一个带有 as? SecIdentity 的编译错误。这个错误对于最后一个守卫是有意义的:每个值都会成功,因为即使firstItem[kSecImportItemIdentity as String] 不是SecIdentity,当向下转换为SecIdentity? 时,它也会变成nil,这满足最后一个守卫(因为可选?)。这使得守卫无用,因此编译错误。这有意义吗? 相关:***.com/q/43927167/2976878 丹尼尔。第一个例子怎么样? 【参考方案1】:

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 The CoreFoundation conditional downcast diagnostic is not as helpful as it should be:

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

【讨论】:

【参考方案2】:

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

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

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

旁注:

请不要写as? SecIdentity?。 要么是有条件的向下转换as? SecIdentity,要么是桥接转换可选的as SecIdentity?

【讨论】:

以上是关于向下转换“任何”时出现 Swift 错误的主要内容,如果未能解决你的问题,请参考以下文章

Swift 解析 JSON 时出现问题:无法将“__NSCFDictionary”类型的值转换为“NSArray”错误

将 .py 转换为 .exe 时出现 cx_Freeze 错误

从“字符串”到“字符串”的条件向下转换总是成功 - Swift 错误

在 swift 3 中打印 json 时出现任何下标成员错误 [重复]

Swift - NSJsonSerialization - “无法将数据转换为围绕字符的字符串”错误

尝试训练数据模型时出现 Swift CreateML 错误。非常感谢任何输入