< Previous PageNext Page > Hide TOC

Saving and Restoring Property Lists

CFPropertyList properly takes care of endian issues—a property list (whether represented by a stream, XML, or a CFData object) created on a PowerPC-based Macintosh is correctly interpreted on an Intel-based Macintosh, and vice versa.

Listing 1 shows you how to create a more complex property list, convert it to XML, write it to disk, and then re-create the original data structure using the saved XML. For more information about using CFDictionary objects see Collections.

Listing 1  Saving and restoring property list data

#include <CoreFoundation/CoreFoundation.h>
 
#define kNumKids 2
#define kNumBytesInPic 10
 
CFDictionaryRef CreateMyDictionary( void );
CFPropertyListRef CreateMyPropertyListFromFile( CFURLRef fileURL );
void WriteMyPropertyListToFile( CFPropertyListRef propertyList,
            CFURLRef fileURL );
 
int main () {
   CFPropertyListRef propertyList;
   CFURLRef fileURL;
 
   // Construct a complex dictionary object;
   propertyList = CreateMyDictionary();
 
   // Create a URL that specifies the file we will create to
   // hold the XML data.
   fileURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,
               CFSTR("test.txt"),       // file path name
               kCFURLPOSIXPathStyle,    // interpret as POSIX path
               false );                 // is it a directory?
 
   // Write the property list to the file.
   WriteMyPropertyListToFile( propertyList, fileURL );
   CFRelease(propertyList);
 
   // Recreate the property list from the file.
   propertyList = CreateMyPropertyListFromFile( fileURL );
 
   // Release any objects to which we have references.
   CFRelease(propertyList);
   CFRelease(fileURL);
   return 0;
}
 
CFDictionaryRef CreateMyDictionary( void ) {
   CFMutableDictionaryRef dict;
   CFNumberRef            num;
   CFArrayRef             array;
   CFDataRef              data;
 
   int                    yearOfBirth;
   CFStringRef            kidsNames[kNumKids];
 
   // Fake data to stand in for a picture of John Doe.
   const unsigned char pic[kNumBytesInPic] = {0x3c, 0x42, 0x81,
            0xa5, 0x81, 0xa5, 0x99, 0x81, 0x42, 0x3c};
 
   // Define some data.
   kidsNames[0] = CFSTR("John");
   kidsNames[1] = CFSTR("Kyra");
 
   yearOfBirth = 1965;
 
   // Create a dictionary that will hold the data.
   dict = CFDictionaryCreateMutable( kCFAllocatorDefault,
            0,
            &kCFTypeDictionaryKeyCallBacks,
            &kCFTypeDictionaryValueCallBacks );
 
   // Put the various items into the dictionary.
   // Because the values are retained as they are placed into the
   //  dictionary, we can release any allocated objects here.
 
   CFDictionarySetValue( dict, CFSTR("Name"), CFSTR("John Doe") );
 
   CFDictionarySetValue( dict,
            CFSTR("City of Birth"),
            CFSTR("Springfield") );
 
   num = CFNumberCreate( kCFAllocatorDefault,
            kCFNumberIntType,
            &yearOfBirth );
   CFDictionarySetValue( dict, CFSTR("Year Of Birth"), num );
   CFRelease( num );
 
   array = CFArrayCreate( kCFAllocatorDefault,
               (const void **)kidsNames,
               kNumKids,
               &kCFTypeArrayCallBacks );
   CFDictionarySetValue( dict, CFSTR("Kids Names"), array );
   CFRelease( array );
 
   array = CFArrayCreate( kCFAllocatorDefault,
               NULL,
               0,
               &kCFTypeArrayCallBacks );
   CFDictionarySetValue( dict, CFSTR("Pets Names"), array );
   CFRelease( array );
 
   data = CFDataCreate( kCFAllocatorDefault, pic, kNumBytesInPic );
   CFDictionarySetValue( dict, CFSTR("Picture"), data );
   CFRelease( data );
 
   return dict;
}
 
void WriteMyPropertyListToFile( CFPropertyListRef propertyList,
            CFURLRef fileURL ) {
   CFDataRef xmlData;
   Boolean status;
   SInt32 errorCode;
 
   // Convert the property list into XML data.
   xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList );
 
   // Write the XML data to the file.
   status = CFURLWriteDataAndPropertiesToResource (
               fileURL,                  // URL to use
               xmlData,                  // data to write
               NULL,
               &errorCode);
 
   CFRelease(xmlData);
}
 
CFPropertyListRef CreateMyPropertyListFromFile( CFURLRef fileURL ) {
   CFPropertyListRef propertyList;
   CFStringRef       errorString;
   CFDataRef         resourceData;
   Boolean           status;
   SInt32            errorCode;
 
   // Read the XML file.
   status = CFURLCreateDataAndPropertiesFromResource(
               kCFAllocatorDefault,
               fileURL,
               &resourceData,            // place to put file data
               NULL,
               NULL,
               &errorCode);
 
   // Reconstitute the dictionary using the XML data.
   propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
               resourceData,
               kCFPropertyListImmutable,
               &errorString);
 
   CFRelease( resourceData );
   return propertyList;
}

Listing 2 shows how the contents of xmlData, created in Listing 1, would look if printed to the screen.

Listing 2  XML file contents created by the sample program

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
        "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Year Of Birth</key>
    <integer>1965</integer>
    <key>Pets Names</key>
    <array/>
    <key>Picture</key>
    <data>
        PEKBpYGlmYFCPA==
    </data>
    <key>City of Birth</key>
    <string>Springfield</string>
    <key>Name</key>
    <string>John Doe</string>
    <key>Kids Names</key>
    <array>
        <string>John</string>
        <string>Kyra</string>
    </array>
</dict>
</plist>
 


< Previous PageNext Page > Hide TOC


© 2006 Apple Computer, Inc. All Rights Reserved. (Last updated: 2006-02-07)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.