Theoretical Question on NSDictionary / NSArray

Discussion in 'iOS Programming' started by ArtOfWarfare, Oct 26, 2012.

  1. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #1
    NSDictionaries and NSArrays aren't typesafe... you use methods like objectForKey: or objectAtIndex:, but you can't be certain of the type you'll be getting back, beyond the fact it'll be an NSObject.

    In the past, I never worried about it because I haven't worried about maintaining my code or ensuring that other people can easily follow it. But now I'm thinking... it seems like using NSDictionary and NSArray are really poor choices for keeping your code easy to follow.

    Rather than store and pass data around in generic classes like NSDictionary and NSArray, wouldn't it be better to make your own NSObject subclass and load it up with properties that store specific types?

    I'm curious, does anyone have some example scenario where it's a better idea to use an NSDictionary or NSArray rather than your own class?

    I guess, while I'm at it, I may as well ask this too... is there any equivalent to a C++/Java Vector class in Obj-C, where you can specify the type of object that a specific collection instance will store? Will you get compile time errors for misusing it? If not, are there any ideas for how you might make your own? Is there any way to add your own compile time checks that generate warnings/errors for when your classes are misused?
     
  2. mfram macrumors 65816

    Joined:
    Jan 23, 2010
    Location:
    San Diego, CA USA
    #2
    I think the big design principle you're missing is the concept of 'introspection'. You can pull an object out of an NSArray or NSDictionary and ask it what type it is if you really want to know. There's no reason to create a "vector" of a specific type because you can put any NSObject type you want in the NSArray.

    C++ is generally much more concerned at compile-time to statically bind the exact type of something. In Objective-C types are not always compiled in statically. Objects are typically typed dynamically at run-time.

    One excellent book to read about these design principles is Cocoa Design Patterns. It goes into great detail the reasons why these decisions were made in the design of the language and frameworks.
     
  3. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #3
    If you want those kind of typesafe containers the use C++. IMO, it's highly over-rated and adds a huge amount of complexity to the language and to your code.

    Most of the time NSArray objects are filled with objects that are all the name type. If you're putting objects of different types into an array you should think about that closely.

    NSDictionary is a bit of a different story. You might have different types in a dictionary. However, each type is identified by a name so your code should be able to know the type of an object based on its name. There may be rare cases where you might have an object in a dictionary that could be of more than one type. Introspection can be used to distinguish them or other methods may be used to distinguish them.

    The flexibility afforded by this loose compile time type safety makes code simpler without adding much in the way of problems. I don't see a lot of beginners posting questions where they've shot themselves in the foot due to this kind of loose type checking.
     
  4. Duncan C macrumors 6502a

    Duncan C

    Joined:
    Jan 21, 2008
    Location:
    Northern Virginia
    #4
    I don't know of any built-in type safe container objects, but it would be trivial to create one.

    Just create a custom object that has an NSArray or NSDictionary inside it as an instance variable, and exposes methods to add objects of a specific type.

    That would be a bit of a pain, though, because you'd have to create a custom object to hold each data type you wanted it to hold. You'd need a StringArray class, a DataArray class, an ImageArray class, etc.

    Alternately, you could create an object who's init method took a Class object as a parameter. It would have generic addObject or addObject:forKey: method that would take objects of type id, but type-check the objects at runtime to verify that they match the specified container type. It would take me about 1/2 hour to design and write such a class.
     
  5. ArtOfWarfare thread starter macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #5
    Excellent idea! Not that I actually need one, but if I ever felt it was necessary, that'd definitely be a start on how to have one... next goal would be figuring out how to add in precompiler warnings... is there any way of doing that, possibly with #if and #warning ?
     
  6. ArtOfWarfare thread starter macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #6
    Revisiting this topics briefly nearly a year later, I'd like to say something that I've learned since that I didn't know when I wrote my original post:

    In C++, vector<string>, vector<int>, and every other vector <type> (including vectors within vectors ad infinitum), is a unique class that's generated at compile time.

    This leads, potentially, to very large binaries full of repetitive code.

    Also, a suggestion that it seems no one offered last year: look into using Obj-C++ instead of straight Obj-C if you'd like such type checking at compile time.

    Also, other things if you want compile time checks (this is down the same rabbit hole I was interested in when I wrote the original post):

    http://oclint.org
     

Share This Page