Create a dictionary property list programmatically

29,803

Solution 1

This is a situation where "teach a man to fish" is a vastly more helpful approach than "give a man a fish". Once you understand the basic principles and the NSDictionary API, it becomes much easier to craft your own custom solution. Here are a few observations and learning points:

  • The method +dictionaryWithObject:forKey: is used to create an NSDictionary with a single key-value pair. It will not accept comma-separated arguments after each colon (:) in the method call, just one. To create a dictionary with multiple key-value pairs, use one of 2 related methods: +dictionaryWithObjects:forKeys: which accepts two NSArray objects containing values and keys, or +dictionaryWithObjectsAndKeys: which alternates (object, key, object, key) with a terminating nil argument.
  • Simplify the creation code. You don't need a million local variables just to create the thing. Use inline arguments where it makes sense. One way to do this it to build up your dictionary in code as an NSMutableDictionary, then (if necessary) make an immutable copy of it by calling -copy on it. (Remember that a copy method returns a new object that you must release to avoid memory leaks.) That way you don't have to have a variable for every single value so you can do a "one shot" creation of the structure(s) at each level.
  • Use +arrayWithObject: for creating an NSArray with a single object.
  • (Style suggestions) Never use an uppercase letter to begin the name of a variable, method, or function. (Notice that SO highlights leading-caps variables like class names.) It will certainly help others who read your code from being confused about your intent by your naming scheme.

Just to give you a flavor of what creating the dictionary in the linked image might look like in code... (I'm ignoring your chosen variable names and using both different approaches for completeness.)

NSDictionary *item1 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"Screen J",[NSNumber numberWithInt:3],nil]
                                                  forKeys:[NSArray arrayWithObjects:@"Title",@"View",nil]];
NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
                                        @"Screen I", @"Title", 
                                        [NSArray arrayWithObject:item1], @"Children", 
                                        nil];
...

Solution 2

I am not sure I understand the basic objective here.

It seems like at runtime, you are constructing a deep dictionary with many child nodes. But you are constructing this all with static code... why can you not simply make a plist (like the one you had an image of) and read that into an NSDictionary? Both NSDictionary and NSArray have methods that let you simply read in a file and get a whole filled out object. Then it is WAY easier to edit and to understand. That method is dictionaryWithContentsOfFile.

If all of the data is truly created at runtime before it is put into the dictionary, then it seems like you would want a very different, recursive, style of code rather than the flat examples given.

Lastly, I personally dislike the dictionaryWithObjects:forKeys: method in NSDictionary for building a dictionary. If you have to do things that way I greatly prefer the alternate method dictionaryWithObjectsAndKeys: which does the same thing but keeps the keys with the objects:

NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
                       @"Screen J",
                       @"Title",
                       [NSNumber numberWithInt:3],
                       @"View"];
Share:
29,803
Admin
Author by

Admin

Updated on July 05, 2020

Comments

  • Admin
    Admin almost 4 years

    I want to programatically create a dictionary which feeds data to my UITableView but I'm having a hard time with it. I want to create a dictionary that resembles this property list (image) give or take a couple of items.

    I've looked at "Property List Programming Guide: Creating Property Lists Programmatically" and I came up with a small sample of my own:

    //keys
    
    NSArray *Childs = [NSArray arrayWithObjects:@"testerbet", nil];
    NSArray *Children = [NSArray arrayWithObjects:@"Children", nil];
    NSArray *Keys = [NSArray arrayWithObjects:@"Rows", nil];
    NSArray *Title = [NSArray arrayWithObjects:@"Title", nil];
    
    //strings
    
    NSString *Titles = @"mmm training";
    
    //dictionary 
    
    NSDictionary *item1 = [NSDictionary dictionaryWithObject:Childs, Titles forKey:Children , Title];
    NSDictionary *item2 = [NSDictionary dictionaryWithObject:Childs, Titles forKey:Children , Title];
    NSDictionary *item3 = [NSDictionary dictionaryWithObject:Childs, Titles forKey:Children , Title];
    NSArray *Rows = [NSArray arrayWithObjects: item1, item2, item3, nil];
    NSDictionary *Root = [NSDictionary dictionaryWithObject:Rows forKey:Keys];
    
    // NSDictionary *tempDict = [[NSDictionary alloc] //initWithContentsOfFile:DataPath];
    NSDictionary *tempDict = [[NSDictionary alloc] initWithDictionary: Root];
    

    I'm trying to use this data of hierachy for my table views.

    So I was wondering how can I can create my property list (dictionary) programmatically so that I can fill it with my own arrays.

    I'm still new with iPhone development so bear with me. ;)

  • Admin
    Admin almost 15 years
    thanks man! ... I'm going to check it out and try to play with it a little see if I get these dictionary thingies right;) I also noticed you didn't use any arrays ( I saw the children for instance in the picture link and the sample app) , I hope it still works;) even if it doesn't you have my gratitude. again thnx..
  • Admin
    Admin almost 15 years
    I wanted to test if I was able to pull it off so to speak so that i could later try to make it indeed more recursive and dynamic for instance a little like this <code>for (int i = 0; i < 4; ++i) { NSMutableArray *theChildren = [NSMutableArray arrayWithCapacity: 1]; [theChildren addObject: [NSString stringWithFormat: @"tester %d", i]]; NSString *aTitle = [NSString </code> You can see the "complete" code below. Indeed my actual objective is of a more dynamic nature.I'm trying to at least get the dictionary to work so I can start making that dynamic. Last but not least Thnx for you feedback