More Problems with archiving.

  • I cannot seem to make keyed archiving work and I dont know why. For
    the outline view I use a simple leaf node structure. I am trying to
    archive and then retrieve that structure so in the nodeitem object
    I've implemented NSCoding and am encoding it as follows:
    -(void)encodeWithCoder:(NSCoder*)coder
    {
    NSLog(@"Encoding root item: %@",self);

    [coder encodeObject:itemParent forKey:@"ItemParent"];
    [coder encodeObject:itemName forKey:@"ItemName"];
    [coder encodeObject:itemType forKey:@"ItemType"];
    [coder encodeObject:children forKey:@"ItemChildren"];
    [coder encodeObject:itemProperties forKey:@"ItemProperties"];
    [coder encodeObject:itemPath forKey:@"ItemPath"];
    [coder encodeObject:itemNote forKey:@"ItemNote"];
    [coder encodeBool:isGroup forKey:@"Expandable"];
    }

    I can see when the file is created that this encoding method is in
    fact being called. And when I look in the data file I can see all the
    keys there.
    However when I attempt to retrieve the data, no matter how I do it,
    it's null. In the NSDocument subclass that I use to hold the
    information about this structure is have implemented:
    - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:
    (NSError **)outError
    {

    if([typeName isEqualTo:@"My Project"]){
      NSLog(@"Opening a project File");
      NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver
    alloc]initForReadingWithData:data];
      projectDict = [[NSMutableDictionary alloc]initWithDictionary:
    [[unarchiver decodeObjectForKey:@"ProjectDict"]retain]];
      projectStruct = [[NSMutableArray alloc]initWithArray:[[unarchiver
    decodeObjectForKey:@"ProjectStruct"]retain]];
      NSData * nodeData = [[unarchiver
    decodeObjectForKey:@"RootNode"]retain];
      NSKeyedUnarchiver * newArch = [[NSKeyedUnarchiver
    alloc]initForReadingWithData:nodeData];
      //I get an error here that the data object is empty.
      _root = [[NodeItem alloc]initWithCoder:newArch];
      NSLog(@"unarchived: %@, %@, %@",_root,projectDict,projectStruct);
      //Here an empty array and empty dictionary print and where it should
    print the root's name it prints null.
      //I have also tried a straight _root = [[unarchiver
    decodeObjectForKey:@"RootNode"]retain]
      return YES;
      }

        return NO;
    }

    The dictionary and array that I encode when creating the project file
    appear to decode correctly however the NSObject subclass that is the
    NodeItem just come out null and I cannot seem to find any possible way
    to get it to actually read the information.

    Finally when the actual document is encoded for writing this is what
    is called":

    -(void)encodeWithCoder:(NSCoder*)coder
    {
    NSLog(@"CAlling encode with coder %@",coder);
    [coder encodeObject:projectDict forKey:@"ProjectDict"];
    [coder encodeObject:projectStruct forKey:@"ProjectStruct"];
    NSData * nodes = [NSKeyedArchiver archivedDataWithRootObject:_root];
    // I've also tried this with a flat [coder encodeObject:_root
    forKey:@"RootNode"];
    NSLog(@"Encoding Data: %@",nodes);
    [coder encodeObject:nodes forKey:@"RootNode"];
    NSLog(@"Reached end of encode");
    }
  • On Dec 4, 2007, at 5:10 PM, Development wrote:

    > I cannot seem to make keyed archiving work and I dont know why. For
    > the outline view I use a simple leaf node structure. I am trying to
    > archive and then retrieve that structure so in the nodeitem object
    > I've implemented NSCoding and am encoding it as follows:
    > -(void)encodeWithCoder:(NSCoder*)coder
    > {
    > NSLog(@"Encoding root item: %@",self);
    >
    > [coder encodeObject:itemParent forKey:@"ItemParent"];
    > [coder encodeObject:itemName forKey:@"ItemName"];
    > [coder encodeObject:itemType forKey:@"ItemType"];
    > [coder encodeObject:children forKey:@"ItemChildren"];
    > [coder encodeObject:itemProperties forKey:@"ItemProperties"];
    > [coder encodeObject:itemPath forKey:@"ItemPath"];
    > [coder encodeObject:itemNote forKey:@"ItemNote"];
    > [coder encodeBool:isGroup forKey:@"Expandable"];
    > }

    I'm going to assume that all your attributes (objects) conform to
    NSCoding.  Having said that, I'm also going to assume that children is
    an ivar of type NSArray that will contain other nodeitem objects?

    Are you only calling this method directly for the top root node?

    > I can see when the file is created that this encoding method is in
    > fact being called. And when I look in the data file I can see all
    > the keys there.
    > However when I attempt to retrieve the data, no matter how I do it,
    > it's null. In the NSDocument subclass that I use to hold the
    > information about this structure is have implemented:
    > - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName
    > error:(NSError **)outError
    > {
    >
    >
    > if([typeName isEqualTo:@"My Project"]){
    > NSLog(@"Opening a project File");
    > NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver
    > alloc]initForReadingWithData:data];
    > projectDict = [[NSMutableDictionary alloc]initWithDictionary:
    > [[unarchiver decodeObjectForKey:@"ProjectDict"]retain]];
    > projectStruct = [[NSMutableArray alloc]initWithArray:[[unarchiver
    > decodeObjectForKey:@"ProjectStruct"]retain]];
    > NSData * nodeData = [[unarchiver
    > decodeObjectForKey:@"RootNode"]retain];
    > NSKeyedUnarchiver * newArch = [[NSKeyedUnarchiver
    > alloc]initForReadingWithData:nodeData];
    > //I get an error here that the data object is empty.
    > _root = [[NodeItem alloc]initWithCoder:newArch];
    > NSLog(@"unarchived: %@, %@, %@",_root,projectDict,projectStruct);
    > //Here an empty array and empty dictionary print and where it
    > should print the root's name it prints null.
    > //I have also tried a straight _root = [[unarchiver
    > decodeObjectForKey:@"RootNode"]retain]
    > return YES;
    > }
    >
    > return NO;
    > }
    >
    > The dictionary and array that I encode when creating the project
    > file appear to decode correctly however the NSObject subclass that
    > is the NodeItem just come out null and I cannot seem to find any
    > possible way to get it to actually read the information.
    >
    >
    > Finally when the actual document is encoded for writing this is what
    > is called":
    >
    >
    > -(void)encodeWithCoder:(NSCoder*)coder
    > {
    > NSLog(@"CAlling encode with coder %@",coder);
    > [coder encodeObject:projectDict forKey:@"ProjectDict"];
    > [coder encodeObject:projectStruct forKey:@"ProjectStruct"];
    > NSData * nodes = [NSKeyedArchiver archivedDataWithRootObject:_root];
    > // I've also tried this with a flat [coder encodeObject:_root
    > forKey:@"RootNode"];
    > NSLog(@"Encoding Data: %@",nodes);
    > [coder encodeObject:nodes forKey:@"RootNode"];
    > NSLog(@"Reached end of encode");
    > }

    I think it would be best to use just a single call to encode/decode
    your entire object structure.  In one of my products, I have a
    classroom object (singleton) that serves as the root object.  I then
    just archive/unarchive that.  In turn, it contains dictionaries of
    arrays/dictionaries/objects that goes pretty deep.  But at the end of
    the day, I end up with a fully rebuilt object structure.

    See the APIs: NSKeyedUnarchiver's unarchiveObjectWithFile: and
    archiveRootObject:toFile:  Also look at their NSData equivalents.

    ___________________________________________________________
    Ricky A. Sharp        mailto:<rsharp...>
    Instant Interactive(tm)  http://www.instantinteractive.com
  • On Dec 4, 2007, at 4:47 PM, Ricky Sharp wrote:

    >
    > On Dec 4, 2007, at 5:10 PM, Development wrote:
    >
    >> I cannot seem to make keyed archiving work and I dont know why. For
    >> the outline view I use a simple leaf node structure. I am trying to
    >> archive and then retrieve that structure so in the nodeitem object
    >> I've implemented NSCoding and am encoding it as follows:
    >> -(void)encodeWithCoder:(NSCoder*)coder
    >> {
    >> NSLog(@"Encoding root item: %@",self);
    >>
    >> [coder encodeObject:itemParent forKey:@"ItemParent"];
    >> [coder encodeObject:itemName forKey:@"ItemName"];
    >> [coder encodeObject:itemType forKey:@"ItemType"];
    >> [coder encodeObject:children forKey:@"ItemChildren"];
    >> [coder encodeObject:itemProperties forKey:@"ItemProperties"];
    >> [coder encodeObject:itemPath forKey:@"ItemPath"];
    >> [coder encodeObject:itemNote forKey:@"ItemNote"];
    >> [coder encodeBool:isGroup forKey:@"Expandable"];
    >> }
    >
    > I'm going to assume that all your attributes (objects) conform to
    > NSCoding.  Having said that, I'm also going to assume that children
    > is an ivar of type NSArray that will contain other nodeitem objects?
    >
    > Are you only calling this method directly for the top root node?

    Yes only on the top node. it automatically calls it for the children,
    I see this via the NSLogs I have.
    And yes all the things I want to archive have <NSCoding> in the header
    and implement initWithCoder/encodeWithCoder, neither of which is
    called automatically it would appear.

    >
    >
    >> I can see when the file is created that this encoding method is in
    >> fact being called. And when I look in the data file I can see all
    >> the keys there.
    >> However when I attempt to retrieve the data, no matter how I do it,
    >> it's null. In the NSDocument subclass that I use to hold the
    >> information about this structure is have implemented:
    >> - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName
    >> error:(NSError **)outError
    >> {
    >>
    >>
    >> if([typeName isEqualTo:@"My Project"]){
    >> NSLog(@"Opening a project File");
    >> NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver
    >> alloc]initForReadingWithData:data];
    >> projectDict = [[NSMutableDictionary alloc]initWithDictionary:
    >> [[unarchiver decodeObjectForKey:@"ProjectDict"]retain]];
    >> projectStruct = [[NSMutableArray alloc]initWithArray:[[unarchiver
    >> decodeObjectForKey:@"ProjectStruct"]retain]];
    >> NSData * nodeData = [[unarchiver
    >> decodeObjectForKey:@"RootNode"]retain];
    >> NSKeyedUnarchiver * newArch = [[NSKeyedUnarchiver
    >> alloc]initForReadingWithData:nodeData];
    >> //I get an error here that the data object is empty.
    >> _root = [[NodeItem alloc]initWithCoder:newArch];
    >> NSLog(@"unarchived: %@, %@, %@",_root,projectDict,projectStruct);
    >> //Here an empty array and empty dictionary print and where it
    >> should print the root's name it prints null.
    >> //I have also tried a straight _root = [[unarchiver
    >> decodeObjectForKey:@"RootNode"]retain]
    >> return YES;
    >> }
    >>
    >> return NO;
    >> }
    >>
    >> The dictionary and array that I encode when creating the project
    >> file appear to decode correctly however the NSObject subclass that
    >> is the NodeItem just come out null and I cannot seem to find any
    >> possible way to get it to actually read the information.
    >>
    >>
    >> Finally when the actual document is encoded for writing this is
    >> what is called":
    >>
    >>
    >> -(void)encodeWithCoder:(NSCoder*)coder
    >> {
    >> NSLog(@"CAlling encode with coder %@",coder);
    >> [coder encodeObject:projectDict forKey:@"ProjectDict"];
    >> [coder encodeObject:projectStruct forKey:@"ProjectStruct"];
    >> NSData * nodes = [NSKeyedArchiver archivedDataWithRootObject:_root];
    >> // I've also tried this with a flat [coder encodeObject:_root
    >> forKey:@"RootNode"];
    >> NSLog(@"Encoding Data: %@",nodes);
    >> [coder encodeObject:nodes forKey:@"RootNode"];
    >> NSLog(@"Reached end of encode");
    >> }
    >
    >
    > I think it would be best to use just a single call to encode/decode
    > your entire object structure.  In one of my products, I have a
    > classroom object (singleton) that serves as the root object.  I then
    > just archive/unarchive that.  In turn, it contains dictionaries of
    > arrays/dictionaries/objects that goes pretty deep.  But at the end
    > of the day, I end up with a fully rebuilt object structure.
    >
    > See the APIs: NSKeyedUnarchiver's unarchiveObjectWithFile: and
    > archiveRootObject:toFile:  Also look at their NSData equivalents.

    I'm only writing because it's obvious to me that I did not understand
    a single word of what I read in these references, in my books or in
    the header files.

    As an Update to this information. I have added data to the array and
    the dictionary and they are not working either. I encode the
    information as all the examples say I am suppose to, or at least my
    understanding of it, and nothing is retrievable. Like I said I can see
    all the information in the file, all the keys etc but for whatever
    reason when I attempt to recall it nothing comes back.

    >
    >
    > ___________________________________________________________
    > Ricky A. Sharp        mailto:<rsharp...>
    > Instant Interactive(tm)  http://www.instantinteractive.com
    >
  • You haven't shown the code which invokes the archiver, but I'm
    guessing you are archiving the document; that would be inconsistent
    with your method of unarchiving.  I would expect to see something
    like the following...

    - (NSData *) dataOfType:(NSString *)typeName error:(NSError **)outError
    {
      NSDictionary *saveDict
          = [NSDictionary dictionaryWithObjectsAndKeys:
                              projectDict, @"ProjectDict",
                              ...
                              nil];
      return [NSKeyedArchiver archivedDataWithRootObject:saveDict];
    }

    - (BOOL) readFromData:(NSData *)data ofType:(NSString *)typeName
    error:(NSError **)outError
    {
      NSDictionary *saveDict = [NSKeyedUnarchiver
    unarchiveObjectWithData:data];
      projectDict = [[NSMutableDictionary alloc] initWithDictionary:
    [saveDict objectForKey:@"ProjectDict"]];
      ...
    }

    As Ricky said, you should be able to use a single archiver/unarchiver
    to encode/decode all relevant objects.

    Note also that mutability of dictionaries and arrays is preserved
    through archiving, so you needn't create mutable copies on unarchiving.

    dave

    On 4-Dec-07, at 5:03 PM, Development wrote:

    >
    > On Dec 4, 2007, at 4:47 PM, Ricky Sharp wrote:
    >
    >>
    >> On Dec 4, 2007, at 5:10 PM, Development wrote:
    >>
    >>> I cannot seem to make keyed archiving work and I dont know why.
    >>> For the outline view I use a simple leaf node structure. I am
    >>> trying to archive and then retrieve that structure so in the
    >>> nodeitem object I've implemented NSCoding and am encoding it as
    >>> follows:
    >>> -(void)encodeWithCoder:(NSCoder*)coder
    >>> {
    >>> NSLog(@"Encoding root item: %@",self);
    >>>
    >>> [coder encodeObject:itemParent forKey:@"ItemParent"];
    >>> [coder encodeObject:itemName forKey:@"ItemName"];
    >>> [coder encodeObject:itemType forKey:@"ItemType"];
    >>> [coder encodeObject:children forKey:@"ItemChildren"];
    >>> [coder encodeObject:itemProperties forKey:@"ItemProperties"];
    >>> [coder encodeObject:itemPath forKey:@"ItemPath"];
    >>> [coder encodeObject:itemNote forKey:@"ItemNote"];
    >>> [coder encodeBool:isGroup forKey:@"Expandable"];
    >>> }
    >>
    >> I'm going to assume that all your attributes (objects) conform to
    >> NSCoding.  Having said that, I'm also going to assume that
    >> children is an ivar of type NSArray that will contain other
    >> nodeitem objects?
    >>
    >> Are you only calling this method directly for the top root node?
    >
    > Yes only on the top node. it automatically calls it for the
    > children, I see this via the NSLogs I have.
    > And yes all the things I want to archive have <NSCoding> in the
    > header and implement initWithCoder/encodeWithCoder, neither of
    > which is called automatically it would appear.
    >
    >
    >>
    >>
    >>> I can see when the file is created that this encoding method is
    >>> in fact being called. And when I look in the data file I can see
    >>> all the keys there.
    >>> However when I attempt to retrieve the data, no matter how I do
    >>> it, it's null. In the NSDocument subclass that I use to hold the
    >>> information about this structure is have implemented:
    >>> - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName
    >>> error:(NSError **)outError
    >>> {
    >>>
    >>>
    >>> if([typeName isEqualTo:@"My Project"]){
    >>> NSLog(@"Opening a project File");
    >>> NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver alloc]
    >>> initForReadingWithData:data];
    >>> projectDict = [[NSMutableDictionary alloc]initWithDictionary:
    >>> [[unarchiver decodeObjectForKey:@"ProjectDict"]retain]];
    >>> projectStruct = [[NSMutableArray alloc]initWithArray:
    >>> [[unarchiver decodeObjectForKey:@"ProjectStruct"]retain]];
    >>> NSData * nodeData = [[unarchiver decodeObjectForKey:@"RootNode"]
    >>> retain];
    >>> NSKeyedUnarchiver * newArch = [[NSKeyedUnarchiver alloc]
    >>> initForReadingWithData:nodeData];
    >>> //I get an error here that the data object is empty.
    >>> _root = [[NodeItem alloc]initWithCoder:newArch];
    >>> NSLog(@"unarchived: %@, %@, %@",_root,projectDict,projectStruct);
    >>> //Here an empty array and empty dictionary print and where it
    >>> should print the root's name it prints null.
    >>> //I have also tried a straight _root = [[unarchiver
    >>> decodeObjectForKey:@"RootNode"]retain]
    >>> return YES;
    >>> }
    >>>
    >>> return NO;
    >>> }
    >>>
    >>> The dictionary and array that I encode when creating the project
    >>> file appear to decode correctly however the NSObject subclass
    >>> that is the NodeItem just come out null and I cannot seem to find
    >>> any possible way to get it to actually read the information.
    >>>
    >>>
    >>> Finally when the actual document is encoded for writing this is
    >>> what is called":
    >>>
    >>>
    >>> -(void)encodeWithCoder:(NSCoder*)coder
    >>> {
    >>> NSLog(@"CAlling encode with coder %@",coder);
    >>> [coder encodeObject:projectDict forKey:@"ProjectDict"];
    >>> [coder encodeObject:projectStruct forKey:@"ProjectStruct"];
    >>> NSData * nodes = [NSKeyedArchiver
    >>> archivedDataWithRootObject:_root];
    >>> // I've also tried this with a flat [coder encodeObject:_root
    >>> forKey:@"RootNode"];
    >>> NSLog(@"Encoding Data: %@",nodes);
    >>> [coder encodeObject:nodes forKey:@"RootNode"];
    >>> NSLog(@"Reached end of encode");
    >>> }
    >>
    >>
    >> I think it would be best to use just a single call to encode/
    >> decode your entire object structure.  In one of my products, I
    >> have a classroom object (singleton) that serves as the root
    >> object.  I then just archive/unarchive that.  In turn, it contains
    >> dictionaries of arrays/dictionaries/objects that goes pretty
    >> deep.  But at the end of the day, I end up with a fully rebuilt
    >> object structure.
    >>
    >> See the APIs: NSKeyedUnarchiver's unarchiveObjectWithFile: and
    >> archiveRootObject:toFile:  Also look at their NSData equivalents.
    >
    > I'm only writing because it's obvious to me that I did not
    > understand a single word of what I read in these references, in my
    > books or in the header files.
    >
    > As an Update to this information. I have added data to the array
    > and the dictionary and they are not working either. I encode the
    > information as all the examples say I am suppose to, or at least my
    > understanding of it, and nothing is retrievable. Like I said I can
    > see all the information in the file, all the keys etc but for
    > whatever reason when I attempt to recall it nothing comes back.
    >

    >
previous month december 2007 next month
MTWTFSS
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
Go to today