SecIdentity + Force Cast Violation: Force casts sh

2019-08-14 16:02发布

问题:

Please dont mark repetitive question.

HI all,

I am doing NSURLAuthenticationMethodClientCertificate in which I am using the following code. In which code is fine if I dont use swiftlint. But when I use swiftlint I am getting this error and unable to solve this. Tried a lot please help me . Posting the code below.

    var items: CFArray?
    //let PKCS12Data = DataSourceManager.sharedInstance.serverPolicyManager?.PKCS12Data
    securityError = SecPKCS12Import(certData, options, &items)

    if securityError == errSecSuccess {
        let certItems: CFArray = items as CFArray!
        let certItemsArray: Array = certItems as Array
        let dict: AnyObject? = certItemsArray.first
        if let certEntry: Dictionary = dict as? Dictionary<String, AnyObject> {

            // grab the identity
            let identityPointer = certEntry["identity"]
            let secIdentityRef = identityPointer as!  SecIdentity
            print("\(String(describing: identityPointer))  :::: \(secIdentityRef)")
            // grab the trust
            let trustPointer: AnyObject? = certEntry["trust"]
            let trustRef: SecTrust? = trustPointer as! SecTrust
            print("\(String(describing: trustPointer))  :::: \(trustRef)")
            // grab the cert
            let chainPointer: AnyObject? = certEntry["chain"]
            identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef!, certArray:  chainPointer!)

        }

    }

I am getting forcecast violation in the below lines.

let secIdentityRef = identityPointer as! SecIdentity

let trustRef: SecTrust? = trustPointer as! SecTrust

回答1:

Basically, what you're doing is a force downcast, meaning that you guarantee that yours identityPointer and trustPointer are objects of SecIdentity and SecTrust classes respectively. But what if they are not? You take them out of the dictionary as AnyObject, so generally they may not cast to the target classes. Swiftlint tells you, that force casting is a bad practise and wants you to avoid it.

However, it seems with CoreFoundation type you can't use a conditional cast as?, so force cast is your only choice. For this particular case you can disable Swiftlint rule in code adding a special comment.

let secIdentityRef = identityPointer as! SecIdentity // swiftlint:disable:this force_cast

To be on the safe side, you also may check the identity of the object by checking the Core Foundation "type id":

guard let identityPointer = certEntry["identity"],
    CFGetTypeID(identityPointer) == SecIdentityGetTypeID() else {
    // here you know that the cast will fail
}
let secIdentityRef = identityPointer as! SecIdentity // swiftlint:disable:this force_cast