Why does CFDictionaryGetValue return a const?

Discussion in 'iOS Programming' started by darkandlong, Sep 26, 2011.

  1. darkandlong macrumors member

    darkandlong

    Joined:
    Jun 19, 2008
    Location:
    Uk
    #1
    I'm struggling to find any explanation for why CFDictionary methods return consts. Can anyone explain this to me?
     
  2. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #2
    Think about where the value originates that CFDictionary returns. Do you know whether that value was const or not? What is safer, if CFDictionary returns a const void* or if it returns a void*?
     
  3. darkandlong thread starter macrumors member

    darkandlong

    Joined:
    Jun 19, 2008
    Location:
    Uk
    #3
    Thanks for replying. I am quite new to the language, so please could you expand on your answer a little. Specifically I am trying to understand how to deal with the value returned to avoid a compiler warning:

    I can get rid of the warning by doing the following:

    Code:
    id const someValue = CFDictionarySetValue(self.mappingConfigByMediatedObjectClass, mediatedObjectClass, mediatorMapping);
    But I want to understand why this is necessary. Why must I declare a local const variable?
     
  4. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #4
    Is there any reason why you're using CFDictionary instead of NSDictionary?

    But your posted code is confusing. CFDictionarySetValue doesn't return anything. CFDictionaryGetValue returns something, but only take 2 paramaters.
     
  5. darkandlong thread starter macrumors member

    darkandlong

    Joined:
    Jun 19, 2008
    Location:
    Uk
    #5
    Sorry. Was very early in the morning.

    I am using CFMutableDictionary because I need to use keys that are not copied. I am programming in cocoa touch so this is unfortunately my only option as I have no access to NSHashTable.

    The correct code should have been:

    id<SomeProtocol> someObject = CFDictionaryGetValue(self.someDictionary, someObjectAsKey);

    So if I set someObject as a const I lose the warning.
     
  6. gnasher729, Sep 27, 2011
    Last edited: Sep 27, 2011

    gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #6
    I would very strongly suggest that if you are new to this, you should _not_ use CFDictionary. It can be tricky to set up, and you need to thoroughly understand it and get it right, especially if you use it to do something that NSDictionary cannot do.

    You will be much better off with a design where both keys and objects are NSObject and where you can use NSDictionary. (And an NSDictionary will _retain_ keys and objects, it will not copy anything).


    The rule is: The language should not allow you to modify a constant value unless you explicitly write something that makes it possible (and the consequences are your fault). CFDictionary cannot know whether you use it to store a const or non-const item. Therefore CFDictionaryGetValue cannot return a non-const pointer, because you could put a pointer to a const object into the dictionary, get a non-const pointer back with CFDictionaryGetValue, and use it to modify the constant data. It is _designed_ to not allow you to do that.

    The assignment to the local variable gave you a warning; exactly for that reason. To remove the warning, you have to explicitly cast the result of CFDictionaryGetValue. That basically tells the compiler "Shut up, I know what I'm doing, if it goes wrong it's all my fault".
     
  7. darkandlong, Sep 27, 2011
    Last edited by a moderator: Sep 28, 2011

    darkandlong thread starter macrumors member

    darkandlong

    Joined:
    Jun 19, 2008
    Location:
    Uk
    #7
    I'm certainly not enjoying my time with CFDictionary so far ;) However, as far as I understand it NSDictionary/NSMutableDictionary will always copy keys. With the CFDictionary I can specify whether I want the keys to be copied when I create it, but with NSDictionary I have no choice.

    The objects I am using as keys are too heavy to be copied and I cannot guarantee they will support NSCopying anyway.

    Thanks. This makes a lot of sense. But how do I cast in this context as I'm not casting to a type, I'm casting a const to be not-a-const?

    ----------

    Ok. So it seems I can just cast it without the const like this:

    Code:
    id<SomeProtocol> someObject = (id<SomeProtocol>)CFDictionaryGetValue(self.someDictionary, someObjectAsKey);
    Which will suppress the warning. Many thanks for your help.
     
  8. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #8
    Perhaps you should consider a lighter key. :)

    I'm curious. What kind of information are you storing in your keys?
     
  9. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #9
    The values that you put into the CFDictionary are const void * so it only makes sense that the values to retrieve from it are the same. Use of this type is a guarantee by the container that it isn't going to modify the value that you add to the container. Since you can't do anything useful with a const void * anyway you must cast it to another type. So casting it in such a way that you remove the const is not a burden.

    In general const isn't very useful in objective-C since all the Foundation Classes (most or all) come in mutable and immutable versions. Using the immutable type serves the same purpose that const serves in some other languages.
     
  10. North Bronson macrumors 6502

    Joined:
    Oct 31, 2007
    Location:
    San José
    #10
    You should be able to create a CFDictionaryRef with your own retain and release callbacks and then use toll-free bridging to cast that CFDictionaryRef as an NSDictionary. You should be able to treat it like any other Cocoa dictionary, except that it should respect your custom callbacks. I have not done a ton of work with Core Foundation, but you might want to give that a try.
     
  11. darkandlong thread starter macrumors member

    darkandlong

    Joined:
    Jun 19, 2008
    Location:
    Uk
    #11
    Thanks for the replies.

    @dejo They are ViewControllers

    @North Bronson Thats what I've ended up doing. Dangerous though. casting is to NSMutableDictionary and using setObject:ForKey: still causes the key to be copied, so adding items has to be done without the cast.
     

Share This Page