respondsToSelector: equivalent for CoreFoundation?

196 views Asked by At

I have a CFArrayRef which mostly has CFDictionaryRef, but sometimes it'll contain other things. I'd like to access a value from the dictionary in the array if I can, and not crash if I can't. Here's the code:

bool result = false;
CFArrayRef devices = CFArrayCreateCopy(kCFAllocatorDefault, SDMMobileDevice->deviceList);
if (devices) {
    for (uint32_t i = 0; i < CFArrayGetCount(devices); i++) {
        CFDictionaryRef device = CFArrayGetValueAtIndex(devices, i);
        if (device) { // *** I need to verify this is actually a dictionary or actually responds to the getObjectForKey selector! ***
            CFNumberRef idNumber = CFDictionaryGetValue(device, CFSTR("DeviceID"));
            if (idNumber) {
                uint32_t fetched_id = 0;
                CFNumberGetValue(idNumber, 0x3, &fetched_id);
                if (fetched_id == device_id) {
                    result = true;
                    break;
                }
            }
        }
    }
    CFRelease(devices);
}
return result;

Any suggestions for how I can ensure that I only treat device like a CFDictionary if it's right to do so?

(I'm dealing with some open source code that isn't particularly well documented, and it doesn't seem to be particularly reliable either. I'm not sure if it's a bug that the array contains non-dictionary objects or a bug that it doesn't detect when it contains non-dictionary objects, but it seems to me that adding a check here is less likely to break other code then forcing it to only contain dictionaries elsewhere. I don't often work with CoreFoundation, so I'm not sure if I'm using the proper terms.)

1

There are 1 answers

1
Phillip Kinkade On BEST ANSWER

In this case, since it looks like you are traversing the I/O Registry, you can use CFGetTypeId():

CFTypeRef device = CFArrayGetValueAtIndex(devices, i);  // <-- use CFTypeRef
if(CFGetTypeID(device) == CFDictionaryGetTypeID()) {    // <-- ensure it's a dictionary
    ...
}

If you really need to send messages to NSObject's interface from your C code, you can (see #include <objc/objc.h> and friends, or call to a C helper function in a .m file), but these strategies are not as straight forward as CFGetTypeID(), and much more error-prone.