Как использовать NSCoder - PullRequest
       8

Как использовать NSCoder

5 голосов
/ 09 ноября 2009

Я занимаюсь разработкой приложения для iPhone.

Я использую 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

Но предупреждаю.

'NSCoder' may not respond to '-decodeDataObjectForKey'

Как использовать NSCoder?

Ответы [ 4 ]

7 голосов
/ 09 ноября 2009

Используйте -decodeObjectForKey: и прочитайте документацию .

3 голосов
/ 09 ноября 2009

Здесь представлены протокольные методы NSCoding из моего объекта LogEntry, хотя вы можете игнорировать оператор switch и детали схемы, хотя они относятся к написанному мною базовому классу, который позволяет мне следить за изменениями форматов данных.

Обратите внимание, что помимо использования decodeObjectForKey: вам также необходимо убедиться, что вы сохраняете / копируете заданные значения, поскольку они автоматически высвобождаются при получении.

- (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];
}
2 голосов
/ 09 ноября 2009

Я думаю, вы должны использовать -decodeObjectForKey:

0 голосов
/ 10 сентября 2013

Я написал вспомогательную функцию для использования NSCoding. Это часть библиотеки VSCore. Проверьте это здесь:

@interface QuickCoding : NSObject

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

@end

И файл .m:

#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

Полный код здесь: https://github.com/voipswitch/VSCore/tree/master/VSCore/Storage

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...