Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Chirone

macrumors 6502
Original poster
Mar 2, 2009
279
0
NZ
so i've spent the day struggling with CFDictionary... it's not as easy as NSDictinary too...

i think i've put stuff into the dictionary:

Code:
CFStringRef key = CFSTR("ChironesKey");
NSString* val = [NSString stringWithFormat: @"%d", [aNumber intValue]];
		
CFStringEncoding encoding = kCFStringEncodingMacRoman;

const char *cstr_hello = [val UTF8String];

CFAllocatorRef alloc_default = kCFAllocatorDefault; 
CFStringRef value = CFStringCreateWithCString(alloc_default, cstr_hello, encoding);
CFDictionaryRef info = CFDictionaryCreate(kCFAllocatorDefault, (const void **)key, (const void**)value, 2, NULL, NULL);
(that's not the actual name of the key, i just did that so you know i'm using a string)
so, i'm trying to store a number into this dictionary with a key.
i think i've done this right, it's basically copy pasted from example code from Apple...

the problem now is... i can't get the value out of it.

i tried what i thought was correct:
Code:
CFStringRef key = CFSTR("VQLineIndex");
		const void* value = CFDictionaryGetValue(userInfo,key);
but it turns out that value is null and doesn't exist...uh... didn't i put in the same key as i used to add the value?

i tried numerous other ways too.

i tried using this:
Code:
CFTypeRef* values; 
int size = CFDictionaryGetCount(userInfo);
values = (CFTypeRef *) malloc( size * sizeof(CFTypeRef) );
CFDictionaryGetKeysAndValues(userInfo, NULL, (const void **) values);
const char* value = (const char*)values[0];
this time value exists, but any attempt to do anything with it results in a runtime error that isn't caught by try-catch
i've tried a few other ways too, but always i either get something that doesn't exist (as with the first example), or something that just causes an uncatchable error (as with the second example)

i read that you can cast a CFDictionary to NSDictionary, so i tried:
Code:
NSDictionary* val = (NSDictionary*)userInfo
no compiler warning or errors but it came with runtime errors that you'd expect if you tried to cast something to something else that it cant cast too...

anyone know the proper way to do this?
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
I'm not sure what userInfo is there, but if you have a CFDictionaryRef you can cast it to NSDictionary* and it'll work fine.

This is what I've used before for creating a dictionary:
Code:
CFMutableDictionaryRef entry = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
And then used CFDictionarySetValue() to add values.

You can also use CFShow() to print a CFTypeRef struct to the console.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,565
There is a multitude of severe bugs in your code.

1. Why are you extracting a UTF-8 string from an NSString and then pass it to a CFString routine and claim that it is MacRoman? It isn't MacRoman, it is UTF8. Go to the header file where the constant for MacRoman was defined and find the correct encoding.

2. Many CF objects and NS objects are toll-free bridged, which means that you can cast one to the other and use it. Take any NSString*, cast it to CFStringRef, and all the CFStringRef functions can be used and vice versa. No need at all to to copy the NSString* in a complicated way.

3. Most people use just NULL instead of kCFAllocatorDefault.

4. But the worst offender by far is your call to CFDictionaryCreate. CFDictionaryCreate creates an immutable dictionary, so all the keys and values must be passed in in the CFDictionaryCreate function. The keys and values could have any type, so they are passed in as void*. However, you want to be able to create dictionaries with more than one key/value pair (one key/value is kind of boring), so you pass in an array of of void*, or a pointer to void*, or a void**. If you have only one key/value pair, you can't pass the key and value itself, you pass the address where they are stored. And since you have _one_ key/value pair, you pass 1, not two.

Furthermore, read the documentation of CFDictionaryCreate and check what the last two parameters should be when your keys and values are CF objects.

So what actually happened is this: You had one CFStringRef containing a key, and one CFStringRef containing a value. You called CFDictionaryCreate and told it that you have two key/value pairs, and you told it that the first CFStringRef is actually a pointer to an array containing two keys, and the second CFStringRef is a pointer to an array containing two values. No wonder that it crashes.
 

Chirone

macrumors 6502
Original poster
Mar 2, 2009
279
0
NZ
so i should really just be using mutable cf dictionaries?

kainjow: sorry, userInfo is a CFDictionary from the CFNotification

thanks for the tips, i wasn't sure how to print CF structs

i did try casting it into an NSDictionary, but as i said, i was getting runtime errors that would occur if the method was non-existant

gnasher: thanks for the analysis and assistance
1- not sure... i don't actually have an excuse for this...

2- i read about that, but somehow it wasn't working... i must have made a mistake in how i was casting... i can't remember what i did because i left the solution behind once it failed... i'll pay more attention to what i'm doing when casting between such things next time.

3- oh.... i just used that because all the examples did

4- so you're saying i told the dictionary it had 2 key/value pairs but it only one got passed into it and so that's why it crashed?
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.