下调“ Any”时出现Swift错误

时间:2018-08-12 04:01:11

标签: swift downcast optional-values

以下代码几乎是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

2 个答案:

答案 0 :(得分: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?

答案 1 :(得分:2)

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(如果可能,使用Fixit)。