views:

353

answers:

3
+1  Q: 

How to use NSCoder

I am developing iphone application.

I use NSCoder.

MyApplication.h

#define ITEMS_KEY @"items"
#define CATEGORIES_KEY @"categories"


#import <UIKit/UIKit.h>


@interface MyApplicationData : NSObject <NSCoding, NSCopying> {
    NSMutableArray* items;
    NSMutableArray* categories;
}

@property (nonatomic ,retain) NSMutableArray* items;
@property (nonatomic, retain) NSMutableArray* categories;


@end

Myapplication.m

#import "MyApplicationData.h"


@implementation MyApplicationData

@synthesize items;
@synthesize categories;

#pragma mark NSCoding
- (void)encodeWithCoder:(NSCoder *)aCoder{
  [aCoder encodeObject:items forKey:ITEMS_KEY];
  [aCoder encodeObject:categories forKey:CATEGORIES_KEY];
}

-(id)initWithCoder:(NSCoder *)aDecoder{
  if(self = [super init]){
    self.items = [aDecoder decodeObjectForKey:ITEMS_KEY];
    self.categories = [aDecoder decodeObjectForKey:CATEGORIES_KEY];
  }
  return self;
}

#pragma mark -
#pragma mark NSCopying
-(id)copyWithZone:(NSZone *)zone{
  MyApplicationData* copy = [[[self class]allocWithZone:zone]init];
  items = [self.items copy];
  categories = [self.categories copy];
  return copy;
}

@end

But warnning.

'NSCoder' may not respond to '-decodeDataObjectForKey'

How to use NSCoder?

+2  A: 

I think you should be using -decodeObjectForKey:

Abizern
+7  A: 

Use -decodeObjectForKey: and read the documentation.

Dave DeLong
+3  A: 

Here is the NSCoding protocal methods from my LogEntry object, you can ignore the switch statement and the schema details though, those are from a base class I have written that allows me to keep sane track of changing data formats.

Please note that in addition to using decodeObjectForKey: you also need to make sure you retain/copy the given values as they are autoreleased when received.

- (id)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];

    if (self != nil) {
     switch ([schemaVersion intValue]) {
      case 2:
       filepath = [[coder decodeObjectForKey:@"filepath"] copy];
       identifier = [coder decodeInt64ForKey:@"identifier"];
       level = [coder decodeIntForKey:@"level"];
       lineNumber = [[coder decodeObjectForKey:@"lineNumber"] retain];
       message = [[coder decodeObjectForKey:@"message"] retain];
       timestamp = [[coder decodeObjectForKey:@"timestamp"] retain];
       break;    
      default:
       [self release], self = nil;
       break;
     }
    }

    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:filepath forKey:@"filepath"];
    [coder encodeInt64:identifier forKey:@"identifier"];
    [coder encodeInt:level forKey:@"level"];
    [coder encodeObject:lineNumber forKey:@"lineNumber"];
    [coder encodeObject:message forKey:@"message"];
    [coder encodeObject:timestamp forKey:@"timestamp"];

    [super encodeWithCoder:coder];
}
Bryan McLemore
Anyone who needs to be reminded to retain or copy those objects also needs a link to the memory management rules: http://developer.apple.com/mac/library/documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html
Peter Hosey
The source code under making was added. Is the problem in this?
marcy
The biggest problem I see in the code you posted is that you don't retain the values you retrieve from the coder.
Bryan McLemore