Next: About this document ... Up: Basic GNUstep Base Library Previous: 3.5 NSMutableDictionary

4 Property Lists

As promised, in this last section we are going to have a quick look at a very interesting feature of GNUstep: the support for property lists.

As we saw, it is very easy to save/read a string to/from a file. GNUstep goes well beyond this. You can save/read any object to/from a file, using the archiving/dearchiving facilities; these facilities are great, but save/read objects in a binary format. For arrays and dictionaries containing only strings, GNUstep provides other facilities (the ones we are interested on here) to save/read them from files in a human-readable (and human-modifiable) format, called a property list. Actually, the set of objects which you can save and read in this way is much more general:

  1. Any string can be saved/read as a property list.
  2. Any array or dictionary containing only objects which can be saved/read as a property list can be also saved/read as a property list.
In practice, any array or dictionary which contains other arrays and dictionaries can be saved/read provided that in the end all the 'final' objects are strings.

To save or read a dictionary or an array of the correct type, you write or read them to/from file in the same way as you do with strings, that is, you use the method -writeToFile:atomically: to write them to files, and the method +dictionaryWithContentsOfFile: (for dictionaries) or the method +arrayWithContentsOfFile: (for arrays) to read them from files.

For example, the following code creates a dictionary which is used to store, for each person, some info; then it saves it to a file in the form of a property list:

#include <Foundation/Foundation.h>

int 
main (void)
{
  NSAutoreleasePool *pool = [NSAutoreleasePool new];
  NSMutableDictionary *dict;
  NSDictionary *dict2;

  dict = [NSMutableDictionary new];
  AUTORELEASE (dict);

  dict2 = [NSDictionary dictionaryWithObjectsAndKeys: 
             @"Nicola", @"Name",
             @"Pero", @"Surname",
             @"n.pero@mi.flashnet.it", @"Email", nil];
  [dict setObject: dict2  forKey: @"Nicola"];

  dict2 = [NSDictionary dictionaryWithObjectsAndKeys: 
             @"Ettore", @"Name",
             @"Perazzoli", @"Surname",
             @"ettore@helixcode.com", @"Email", nil];
  [dict setObject: dict2  forKey: @"Ettore"];

  dict2 = [NSDictionary dictionaryWithObjectsAndKeys: 
             @"Richard", @"Name",
             @"Frith-Macdonald", @"Surname",
             @"richard@brainstorm.co.uk", @"Email", nil];
  [dict setObject: dict2  forKey: @"Richard"];

  if ([dict writeToFile: @"/home/nico/testing" atomically: YES])
    {
      NSLog (@"Success");
    }
  else
    {
      NSLog (@"Failure");
    }

  return 0;
}
I tried it on my machine (I encourage you to do the same on yours) and it wrote the following into my /home/nico/testing file:
{
    Ettore = {
        Email = "ettore@helixcode.com";
        Name = Ettore;
        Surname = Perazzoli;
    };
    Nicola = {
        Email = "n.pero@mi.flashnet.it";
        Name = Nicola;
        Surname = Pero;
    };
    Richard = {
        Email = "richard@brainstorm.co.uk";
        Name = Richard;
        Surname = "Frith-Macdonald";
    };
}
As you see, it is a very simple format, and very nice to read and edit manually. The " (speech-marks) are used whenever a string contains spaces or special characters; they are omitted for simple strings. Dictionaries are saved as in
{
  Email = "richard@brainstorm.co.uk";
  Name = Richard;
  Surname = "Frith-Macdonald";
}
(Note that they use curly brackets, and each key/value pairs is followed by a ; (semicolon), even the last one). Arrays (not shown in the previous example) are saved as in
(
 "Nicola Pero", 
 "Ettore Perazzoli", 
 "Richard Frith-Macdonald"
)
(they use round brackets, and each entry is followed by a comma, except the last one). You can find other examples of this format by looking inside your  /GNUstep directory.

One of the advantages of this format is that it is very general, but still very portable and simple. It is so easy and simple (unless XML) that you can write a complete parser/unparser for a new platform in one or two days.

Once you have saved the data to a file in the form of a property list, you can easily retrieve it from the same file. The following code retrieves the data from the file /home/nico/testing, and prints out the Email of Ettore:

#include <Foundation/Foundation.h>

int 
main (void)
{
  NSAutoreleasePool *pool = [NSAutoreleasePool new];
  NSDictionary *dict;
  NSDictionary *dict2;
  NSString *email;

  dict = [NSDictionary dictionaryWithContentsOfFile: 
                         @"/home/nico/testing"];
  dict2 = [dict objectForKey: @"Ettore"];
  email = [dict2 objectForKey: @"Email"];

  NSLog (@"Ettore's Email is: %@", email);

  return 0;
}

Next: About this document ... Up: Basic GNUstep Base Library Previous: 3.5 NSMutableDictionary
2008-01-16