The following code is almost exact replica from Apple Documentation and compiles without errors:
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()
}
The line marked with !!!
contains forced downcast, while replacing as!
with as
quite obviously results in a compilation error 'Any?' is not convertible to 'SecIdentity?'...
Indeed SecIdentity
is a class while Any
may not even be a class.
What I really cannot explain is the following. If I try to make the code safer, by using this
guard let idenity = firstItem[kSecImportItemIdentity as String] as? SecIdentity
else {
throw AnError()
}
or this
guard let idenityRef = firstItem[kSecImportItemIdentity as String] as? SecIdentity?
else {
throw AnError()
}
I get a compilation error: Conditional downcast to CoreFoundation type 'SecIdentity' will always succeed
SecIdentity
is “an abstract Core Foundation-type object representing an identity, ” and the type of Core Foundation types can be
checked with CFGetTypeID()
. So you can check the type ID first. If it matches the type ID of an
SecIdentity
then the forced cast is safe:
guard let cfIdentity = firstItem[kSecImportItemIdentity as String] as CFTypeRef?,
CFGetTypeID(cfIdentity) == SecIdentityGetTypeID() else {
throw AnError()
}
let identity = cfIdentity as! SecIdentity
See also the bug report SR-7015 The CoreFoundation conditional downcast diagnostic is not as helpful as it should be:
The diagnostic should be updated with a message that informs the developer to compare CFTypeIds (with a fixit if possible).
CoreFoundation types behave a bit differently from Foundation types.
Don't conditional downcast the identity. If the optional binding succeeds you can force unwrap the identity
guard let idenity = firstItem[kSecImportItemIdentity as String] else { throw AnError() }
var privateKey : SecKey?
let status = SecIdentityCopyPrivateKey(identity as! SecIdentity, &privateKey)
Side note :
Please never write as? SecIdentity?
.
Either it's conditional downcast as? SecIdentity
or bridge cast an optional as SecIdentity?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With