以下代码几乎是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
答案 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)。