Doe Doe - 2 months ago 221
Swift Question

Cannot invoke initializer for type UnsafeMutablePointer<UInt8>

I'm trying to convert my string into SHA256 hash, but I get the next error:

Cannot invoke initializer for type 'UnsafeMutablePointer<UInt8>' with an argument list of type '(UnsafeMutableRawPointer)'


That's my function:

func SHA256(data: String) -> Data {
var hash = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))!

if let newData: Data = data.data(using: .utf8) {
let bytes = newData.withUnsafeBytes {(bytes: UnsafePointer<CChar>) -> Void in
CC_SHA256(bytes, CC_LONG(newData.length), UnsafeMutablePointer<UInt8>(hash.mutableBytes))
}
}

return hash as Data
}


so, for this part

UnsafeMutablePointer<UInt8>(hash.mutableBytes)


I get this error:

Cannot invoke initializer for type 'UnsafeMutablePointer<UInt8>' with an argument list of type '(UnsafeMutableRawPointer)'


How can I fix that and what I do wrong?

Answer

You'd better use Data also for the result hash.

In Swift 3, withUnsafePointer(_:) and withUnsafeMutablePointer(:_) are generic types and Swift can infer the Pointee types correctly when used with "well-formed" closures, which means you have no need to convert Pointee types manually.

func withUnsafeBytes((UnsafePointer) -> ResultType)

func withUnsafeMutableBytes((UnsafeMutablePointer) -> ResultType)

func SHA256(data: String) -> Data {
    var hash = Data(count: Int(CC_SHA256_DIGEST_LENGTH))

    if let newData: Data = data.data(using: .utf8) {
        _ = hash.withUnsafeMutableBytes {mutableBytes in
            newData.withUnsafeBytes {bytes in
                CC_SHA256(bytes, CC_LONG(newData.count), mutableBytes)
            }
        }
    }

    return hash
}

In Swift 3, the initializers of UnsafePointer and UnsafeMutablePointer, which was used to convert Pointee types till Swift 2, are removed. But in many cases, you can work without type conversions of pointers.