Search code examples
swiftusbiokit

Crash using CFDictionarySetValue in Swift


I'm developing a program in Swift (for a macOS application) that uses IOKit to retrieve information from a USB device. The app crahes with:

Thread 1: EXC_BAD_ACCESS (code=1,...

on setting CFDictionarySetValue. I used the following code:

var matchingDict: CFMutableDictionary?
var val: NSNumber.IntegerLiteralType
var valRef: CFNumber?

matchingDict = IOServiceMatching(kIOHIDDeviceKey)
if let matchingDict {
    val = 1917
    valRef = CFNumberCreate(kCFAllocatorDefault, CFNumberType.sInt32Type, UnsafeMutableRawPointer?(&val))
    CFDictionarySetValue(matchingDict, UnsafeRawPointer?(kIOHIDVendorIDKey), unsafeBitCast(valRef, to: UnsafeRawPointer.self))

I've tried different CFDictionarySetValue config:

valRef = CFNumberCreate(kCFAllocatorDefault, .sInt32Type, UnsafeMutableRawPointer?(&val))

this rise up a warning (and running it causes a crash):

Forming 'UnsafeRawPointer' to a variable of type 'Optional'; this is likely incorrect because 'Optional' may contain an object reference.

then this one:

CFDictionarySetValue(matchingDict, unsafeBitCast(kIOHIDVendorIDKey, to: UnsafeRawPointer.self), unsafeBitCast(valRef, to: UnsafeRawPointer.self))

Complies Ok but then crashes.

Finally:

CFDictionarySetValue(matchingDict, UnsafeRawPointer?(kIOHIDVendorIDKey), unsafeBitCast(valRef, to: UnsafeRawPointer.self))

but it crashes anyway.

What am I doing wrong?


Solution

  • Instead of updating a CFMutableDictionary it is much easier to convert it to a Swift Dictionary. After adding dictionary values, you can convert it back to a CFDictionary if that is needed for further calls:

    if var matchingDict = IOServiceMatching(kIOHIDDeviceKey) as? [String: Any] {
        // Add values:
        matchingDict[kIOHIDVendorIDKey] = 1917
        
        let cfDict = matchingDict as CFDictionary
        // ...
    }