Search code examples
iosswiftcastingunsafe-pointersmigrating

Casting UnsafeMutablePointers to UnsafeMutableRawPointers


I have a couple of issues updating to swift 3.0. I have the following code:

  // Retrieve the Device GUID
        let device = UIDevice.current
        let uuid = device.identifierForVendor
        let mutableData = NSMutableData(length: 16)
        (uuid! as NSUUID).getBytes(UnsafeMutablePointer(mutableData!.mutableBytes))

        // Verify the hash
        var hash = Array<UInt8>(repeating: 0, count: 20)
        var ctx = SHA_CTX()
        SHA1_Init(&ctx)
        SHA1_Update(&ctx, mutableData!.bytes, mutableData!.length)
        SHA1_Update(&ctx, (opaqueData1! as NSData).bytes, opaqueData1!.count)
        SHA1_Update(&ctx, (bundleIdData1! as NSData).bytes, bundleIdData1!.count)
        SHA1_Final(&hash, &ctx)
        let computedHashData1 = Data(bytes: UnsafePointer(&hash), count: 20)

My first issue is with the line of code:

(uuid! as NSUUID).getBytes(UnsafeMutablePointer(mutableData!.mutableBytes))

mutableData!.mutableBytes now returns an UnsafeMutableRawPointer and the compiler complains that "cannot invoke initializer for type 'UnsafeMutablePointer<_> with an argument of type '(UnsafeMutableRawPointer)'" Now I have been trying to cast them to the same types but have had no success.

My second issue is with the line:

let computedHashData1 = Data(bytes: UnsafePointer(&hash), count: 20)

This line causes a compiler error "Ambiguous use of 'init'"


Solution

  • Your first issue, you can write something like this:

        (uuid! as NSUUID).getBytes(mutableData!.mutableBytes.assumingMemoryBound(to: UInt8.self))
    

    But if you can accept Data having the same raw UUID bytes, you can write it as:

        var uuidBytes = uuid!.uuid
        let data = Data(bytes: &uuidBytes, count: MemoryLayout.size(ofValue: uuidBytes))
    

    Your second issue, in Data.init(bytes:count:), the type of the first parameter is UnsafeRawPointer, to which you can pass arbitrary type of Unsafe(Mutable)Pointers.

    Using Swift with Cocoa and Objective-C (Swift 3)

    Check the Constant Pointers part of Pointers.

    When a function is declared as taking an UnsafeRawPointer argument, it can accept the same operands as UnsafePointer<Type> for any type Type.

    You have no need to cast pointer types.

        let computedHashData1 = Data(bytes: &hash, count: 20)