How to use NSCoder

I am developing iphone application.

I use NSCoder.

  • How to check whether a string contains white spaces
  • How to create a top fade effect using UIScrollView?
  • ios writeToFile changes don't save
  • What exactly does a nib file look like if you were to look inside?
  • Accelerometer Low Pass Filtering
  • How to display Text on a PieChart?
  • 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?

    4 Solutions Collect From Internet About “How to use NSCoder”

    Use -decodeObjectForKey: and read the documentation.

    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];
    }
    

    I think you should be using -decodeObjectForKey:

    I wrote a helper function for using NSCoding. It’s a part of VSCore Library. Check it out here:

    @interface QuickCoding : NSObject
    
    + (void)quickEncode:(NSObject<NSCoding>*)object withEncoder:(NSCoder*)encoder;
    + (void)quickDecode:(NSObject<NSCoding>*)object withDecoder:(NSCoder*)decoder;
    
    @end
    

    And the .m file:

    #import "QuickCoding.h"
    #import "ReflectionHelper.h"
    
    #define QUICK_CODING_HASH   @"h4"
    
    @implementation QuickCoding
    
    + (void)quickEncode:(NSObject<NSCoding>*)object withEncoder:(NSCoder *)encoder{
        NSArray *codingKeys = [ReflectionHelper fieldsList:[object class]];
        NSUInteger hash = [[codingKeys componentsJoinedByString:@""] hash];
        [encoder encodeObject:@(hash) forKey:QUICK_CODING_HASH];
    
        [codingKeys enumerateObjectsUsingBlock:^(NSString *key, __unused NSUInteger idx, __unused BOOL *stop) {
            id val = [object valueForKey:key];
            if ([val conformsToProtocol:@protocol(NSCoding)]){
                [encoder encodeObject:val forKey:key];
            }
        }];
    }
    
    + (void)quickDecode:(NSObject<NSCoding>*)object withDecoder:(NSCoder *)decoder{
        NSArray *codingKeys = [ReflectionHelper fieldsList:[object class]];
        NSUInteger hash = [[codingKeys componentsJoinedByString:@""] hash];
        NSUInteger decodedHash = [[decoder decodeObjectForKey:QUICK_CODING_HASH] unsignedIntegerValue];
        BOOL equalHash = hash == decodedHash;
    
        [codingKeys enumerateObjectsUsingBlock:^(NSString *key, __unused NSUInteger idx, __unused BOOL *stop) {
            id val = [decoder decodeObjectForKey:key];
            if (equalHash || val){
                [object setValue:val forKey:key];
            }
        }];
    }
    
    @end
    

    Full code is here: https://github.com/voipswitch/VSCore/tree/master/VSCore/Storage