macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Using Perl to Manage Plist Files, Part 2
Pages: 1, 2, 3, 4, 5, 6

Create a Plist File from Scratch

The last task we want to perform is creating a Plist from scratch. There are several ways we can do this. We could create the base dictionary and add each item to the dictionary one by one.

The more common method is to build the Plist starting with the deepest objects, then their parent containers, one by one, until the last container you build is the root dictionary.

Since the deepest objects are ints, strings, boolean, etc., let's go over creating those objects. Then we will cover creating the dictionary and array containers.

When adding Perl scalar variables to NSArrays or NSDictionaries, they are automatically converted to NSString objects. If we want the int, float, boolean, date, or data objects, we must create an object of that type using the Cocoa factory methods. Here are several shortcut subroutines that will create and return each type of object, except for NSData.


sub cocoaInt {
  return NSNumber->numberWithLong_( $_[0] );
}

sub cocoaBool {
  return NSNumber->numberWithBool_( $_[0] );
}

sub cocoaFloat {
  return NSNumber->numberWithDouble_( $_[0] );
}

sub cocoaDate {
  return NSDate->dateWithTimeIntervalSince1970_( $_[0] );
}

Each of these subroutines will return a Cocoa object with the specified value. There are many other ways to create these objects, but these methods should be easy to use and will probably suffice. We can just put these in our library file.

Now on to the container classes. To create an empty dictionary, use:

$dict = NSMutableDictionary->dictionary();
To create a dictionary with one object, use:
$dict = NSMutableDictionary->dictionaryWithObject_forKey_("Obj", "Key");

Then we want to add objects to these dictionaries using setObject_forKey_() as described in the section, "Changing a Plist Value," earlier in the article.

$plist->setObject_forKey_("some object", "some key");

Adding each object one-by-one can be tedious. It would be nice to create a fully populated dictionary at one time. NSDictionary has the method dicitonaryWithObjects:forKeys: (which allows us to create a fully populated dictionary) but unfortunately this method does not work with the bridge. (See the PerlObjCBridge man page on varargs.)

To create an NSArray or NSDictionary all at once, we can write subroutines that add the objects one-by-one for us. In fact, because the parameter is either an array or a hash, the subroutines just convert a Perl hash or array into the Cocoa equivalent. We can just put these in our library file.

sub cocoaDictFromPerlHash {
  my ( %hash ) = ( @_ );
  my $cocoaDict = NSMutableDictionary->dictionary();
  while ( my ( $key, $value ) = each( %hash ) ) {
    if ( defined $value ) {
      if ( ref ( $value ) eq "ARRAY" ) {
        $cocoaDict->setObject_forKey_( cocoaArrayFromPerlArray( @$value ), 
                                       $key );
      } elsif ( ref ( $value ) eq "HASH" ) {
        $cocoaDict->setObject_forKey_( cocoaDictFromPerlHash( %$value ), 
                                       $key );
      } elsif ( ref ( $value ) eq "SCALAR" ) {
        $cocoaDict->setObject_forKey_( $$value, $key );
      } elsif ( substr ( ref ( $value ), 0,4 ) eq "NSCF" ) {
        $cocoaDict->setObject_forKey_( $value, $key );
      } else {
        $cocoaDict->setObject_forKey_( "$value", $key );
      }
    } else {
      print STDERR "The value was not defined for $key!\n";
    }
  }
  return $cocoaDict;
}

sub cocoaArrayFromPerlArray {
  my ( @perlArray ) = ( @_ );
  my $cocoaArray = NSMutableArray->array();
  foreach my $value ( @perlArray ) {
    if ( defined $value ) {
      if ( ref ( $value ) eq "ARRAY" ) {
        $cocoaArray->addObject_( cocoaArrayFromPerlArray( @$value ) );
      } elsif ( ref ( $value ) eq "HASH" ) {
        $cocoaArray->addObject_( cocoaDictFromPerlHash( %$value ) );
      } elsif ( ref ( $value ) eq "SCALAR" ) {
        $cocoaArray->addObject_( $$value );
      } elsif ( substr ( ref ( $value ), 0,4 ) eq "NSCF" ) {
        $cocoaArray->addObject_( $value );
      } else {
        $cocoaArray->addObject_( "$value" );
      }
    } else {
      print STDERR "The value was not defined!\n";
    }
  }
  return $cocoaArray;
}

Pages: 1, 2, 3, 4, 5, 6

Next Pagearrow