Read & Write Dictionaries, Arrays, Strings To Property List

Property lists are commonly used in iPhone applications. For example, every application has a property list to store the bundle ID, bundle display name, etc.

What follows is partial property list for an application:

< ?xml version="1.0" encoding="UTF-8"?>
< !DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleDevelopmentRegion</key>
  <string>en</string>
  <key>CFBundleDisplayName</key>
  <string>${PRODUCT_NAME}</string>
  <key>CFBundleIdentifier</key>
  <string>com.3Sixty.Test</string>
  <key>CFBundleName</key>
  <string>${PRODUCT_NAME}</string>
 
  ...
 
  <key>UISupportedInterfaceOrientations</key>
  <array>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
  </array>
</dict>
</plist>

Notice the property list is a dictionary of key-value pairs. Further, the last key-value pair has an array as the value object.

iOS provides methods to easily save and restore structured data that you create in your application as property lists. For example, the code below creates a dictionary which contains three arrays.

NSArray *array1 = [NSArray arrayWithObjects:@"string1", @"string2", nil];
NSArray *array2 = [NSArray arrayWithObjects:@"string3", @"string4", nil];
NSArray *array3 = [NSArray arrayWithObjects:@"string5", @"string6", nil];
 
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setObject:array1 forKey:@"Array1"];
[dictionary setObject:array2 forKey:@"Array2"];
[dictionary setObject:array3 forKey:@"Array3"];

Assuming this data was something that you created within your app and wanted to save and restore at another point, here is how you can serialize the dictionary:

NSString *error;   
NSData *data = [NSPropertyListSerialization dataFromPropertyList:dictionary 
  format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
 
// Serialize property list to data object
NSData *data = [NSPropertyListSerialization dataFromPropertyList:dictionary ]
  format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorString];
 
// Path in the documents directory to save file
NSString  *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/test.xml"];
 
// Write the data to file
[data writeToFile:path atomically:YES];

Here is how the data looks in the file test.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Array1</key>
  <array>
    <string>string1</string>
    <string>string2</string>
  </array>
  <key>Array2</key>
  <array>
    <string>string3</string>
    <string>string4</string>
  </array>
  <key>Array3</key>
  <array>
    <string>string5</string>
    <string>string6</string>
  </array>
</dict>
</plist>

To read the property list back into a dictionary:

 
NSString *error;  
NSPropertyListFormat format;   
 
// Build path to the property list (xml file)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
if ([paths count] > 0)
{
  // The file saved previously
  NSString  *plistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"test.xml"];
 
  // Check for existence of the file
  if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath])
  {
    // Read the file
    NSData *data = [NSData dataWithContentsOfFile:plistPath];   
 
    // Saved as dictionary object, so cast from id to dictionary is safe
    NSDictionary *plist = [NSPropertyListSerialization propertyListFromData:data 
        mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];  
 
    NSLog(@"plist: %@", plist);
  }
}