Getting a struct back from an NSValue object

Discussion in 'Mac Programming' started by RossOliver, Jul 8, 2008.

  1. RossOliver macrumors regular

    Nov 6, 2006

    I need to store C structures in an NSArray, so I wrap them in an NSValue object and then shove that object in:

    typedef struct {...} MyStruct;
    NSString *key = @"whatever";
    NSValue *myStructPtr = [NSValue value:&myStruct withObjCType:@encode( MyStruct )];
    [myDictionary myStructPtr forKey:key];
    My question is how do I get them back out? Get the void pointer and cast it to the struct type then dereference? I would have thought the NSValue class would have a method to getValue withObjCType :confused:

    Thanks for your time,

  2. Enuratique macrumors 6502

    Apr 28, 2008
    Interesting concept you're trying here. For starters, the documentation mentions that the value: withObjCType method may be deprecated in the future and that you should use the valueWithBytes: withObjCType: method instead.

    But really, what I think you're trying to do is the valueWithPointer static method. The valueWithBytes will attempt to copy the contents of your pointer into the dictionary where as valueWithPointer will just store the pointer. The documentation for this method does make mention that you should not deallocate the memory pointed at by your pointer because if you pull it out of the dictionary and try to dereference it, it may no longer be a valid pointer. So unless you structs are defined in a method's local scope and you're doing all of your work with the dictionary in that method, then I think the structs will be taken off the stack when the method ends (and your locally defined structs fall out of scope). Thus I can see why you might try the valueWithBytes.

    The documentation also says for arbitrary pointers, NSData is a better suited class than NSValue. Which got me to thinking, you're just trying to store a struct in a dictionary for later use, right? There are ways to serialize primitives into an NSData object which you can than easily store into your dictionary and then deserialize when you need it back into a struct. Check out this documentation.
  3. RossOliver thread starter macrumors regular

    Nov 6, 2006
    The document you linked to seems to make sense, but unfortunately the serializing primitive data methods are deprecated:

    I looked at NSPropertyListSerialization and unfortunately it is bound to certain types:

    Is there another class that has superseded NSMutableData for primitive serialization?


  4. Enuratique macrumors 6502

    Apr 28, 2008

    Try looking into the Archiving and Serialization Programming Guide. Of specific interest, look into Encoding and Decoding C Data Types and how that fits into the Apple's Serialization frameworks.

    Now, this may seem like a silly question, but is it really necessary to use a struct? Could you not define a very simple container class that inherits from NSObject instead and use it? Might save you a lot of trouble unless you need this struct to interoperate with an existing piece of code that is written in C/C++ and not Objective C.

    Happy hacking,

  5. RossOliver thread starter macrumors regular

    Nov 6, 2006
    The structure simply contains two fields - I want to make my application as efficient as possible and the overhead of creating objects instead of structures would be quite significant I think - although there will be overhead in the serializing/de-serializing so I guess it's a lose-lose situation. Creating a whole new class for just two fields is a bit messy I feel though...

    I'll take a look at those documents and see if I can work anything out - thanks for your help :)

  6. Enuratique macrumors 6502

    Apr 28, 2008
    Eh, you'd be surprised at how efficient the compiler is at optimizing things. Yes, you're right trying to serialize/deserialize is a lose-lose situation. Can you elaborate a little bit more on what you're doing with these structs and why they need to be persisted? The one downside to the convenience of all these collection classes in the SDK is that they required objects - they don't play too nicely with C primitives... If you absolutely do not need to reference them by key (ergo, don't need a dictionary) then I'd just say go with old-school C arrays for persistence.

    There is Kazlib, a C implementation of a dictionary, but bringing in that library would probably be WAY overkill. Honesly, I think the quickest fix would be a simple container class... I wrote a very simple node object that only has two properties in it - a dictionary and an array. It's not as bad as you would think and it operates quickly enough.
  7. RossOliver thread starter macrumors regular

    Nov 6, 2006
    By messy I meant the source code would be messy - I'm a bit OCD that way...

    I don't want to give away any information on my program, but the structs are created after each continuous button press by the user and reference later, hence they must be indexed into a dictionary.

    I've written custom encoding/decoding methods using NSKeyedArchiver/NSKeyedUnarchiver and it seems to work well - thanks again for the reference :)

  8. Enuratique macrumors 6502

    Apr 28, 2008
    Cheers, glad to help. Sorry you had to go that route in the first place but sounds like performance isn't too much of a hit.

Share This Page