简体   繁体   English

如何使用NSCoder

[英]How to use NSCoder

I am developing iphone application. 我正在开发iphone应用程序。

I use NSCoder. 我使用NSCoder。

MyApplication.h 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 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? 如何使用NSCoder?

使用-decodeObjectForKey:阅读文档

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. 这是来自我的LogEntry对象的NSCoding协议方法,您可以忽略switch语句和架构详细信息,但这些来自我编写的基类,可以让我保持对更改数据格式的理解。

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. 请注意,除了使用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];
}

我认为你应该使用-decodeObjectForKey:

I wrote a helper function for using NSCoding. 我编写了一个使用NSCoding的辅助函数。 It's a part of VSCore Library. 它是VSCore库的一部分。 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: 和.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

Full code is here: https://github.com/voipswitch/VSCore/tree/master/VSCore/Storage 完整代码在这里: https//github.com/voipswitch/VSCore/tree/master/VSCore/Storage

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM