2

NSObject から継承した XYZ というクラスと、XYZ のオブジェクトを含む配列があります。この配列をドキュメント ディレクトリの plist ファイルに書き込む必要があります。[array writeToFile....] を試したところ、配列に XYZ クラスのカスタム オブジェクトが含まれているため、writeToFile が失敗することがわかりました。

これに対する可能な解決策は、オブジェクトを NSData に変換することです。これを達成するためのさまざまな方法は何ですか?? NSCodingが適していることがわかりましたが、使い方がわかりません。どんな助けでも大歓迎です。

4

5 に答える 5

9

Ray Wenderlich のブログには、NSCoding の操作方法を説明する非常に優れたチュートリアルがあります。

単純に、次のような NSCoding プロトコルを尊重するオブジェクトに*-(void)encodeWithCoder:(NSCoder )encodeおよび *-(id)initWithCoder:(NSCoder )decoderメソッドを実装する必要があります。

// Header
@interface AnObject: NSObject <NSCoding>

// Implementation
- (void) encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:ivar1 forKey:@"ivar1"];
    [encoder encodeFloat:ivar2 forKey:@"ivar2"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super initWithCoder:coder];
    ivar1 = [[coder decodeObjectForKey:@"ivar1"] retain];
    ivar2 = [[coder decodeObjectForKey:@"ivar2"] retain];
    return self;
}

公式ドキュメントはこちらでも確認できます。

于 2011-11-13T13:58:05.480 に答える
9

カスタムクラスを実装encodeWithCoder:initWithCoder:た後、ここに書き方と読み方があります:

書く:

NSError  *error;
NSData* archiveData = [NSKeyedArchiver archivedDataWithRootObject:yourClassInstance];
[archiveData writeToFile:filePath options:NSDataWritingAtomic error:&error];

読んだ:

NSData *archiveData = [NSData dataWithContentsOfFile:filePath];
YourClass *yourClassInstance = (NSArray*)[NSKeyedUnarchiver unarchiveObjectWithData:archiveData];
于 2011-11-13T14:00:45.047 に答える
1

XYZ クラスをNSCodingプロトコルに準拠させることは、実際にやろうとしていることに非常に適しています。これを行うには、NSCoding プロトコルをクラスのインターフェイス宣言に追加します。

@interface XYZ <NSCoding>

次に、encodeWithCoder: と initWithCoder: を実装に実装する必要があります。「コーダーでエンコードする」とは、「オブジェクトの現在の状態を取得し、それを「エンコーダー」と呼ばれる汎用オブジェクトにパックする」ことを意味します。「コーダーで初期化」とは、「既にパックされたエンコーダー オブジェクトが与えられた場合、エンコーダーにパックされたデータで自分自身を構成する」ことを意味します。これらの方法の両方で、「エンコーダー」はNSCoderのインスタンスになり、基本型のエンコード (「パッキング」) とデコード (「アンパック」) のためのかなり単純なインターフェースを持ちます。

実装例は次のとおりです。

@implementation XYZ
- (id)initWithCoder:(NSCoder*)encoder
{
    self = [self init];

    if (self)
    {
        self.myIntProperty = [encoder decodeIntForKey:@"myInt"];
    }

    return self;
}

– (void)encodeWithCoder:(NSCoder*)decoder
{
    [decoder encodeInt:self.myIntProperty forKey:@"myInt"];
}

@end
于 2011-11-13T14:07:38.210 に答える
0

との 2 つのメソッドを実装する必要があり-initWithCoder:ます-encodeWithCoder:NSCodingドキュメントを読んでください。それらは非常に簡単な方法です。基本的に、インスタンス変数をその名前に対応するキーでエンコード/デコードする必要があります。

于 2011-11-13T13:55:57.743 に答える
0

それはかなり簡単です。指定されたクラスの場合Foo:

#import <Foundation/Foundation.h>

@interface Foo : NSObject <NSCoding> {
    NSArray* bar_;
    NSUInteger baz_;
}

@property (nonatomic, retain) NSArray *bar;
@property (nonatomic, assign) NSUInteger baz;

@end

NSCodingプロトコルに準拠するために必要なのは、initWithCoder:およびdecodeWithCoderメッセージを実装することだけです。

#import "Foo.h"

@implementation Foo
@synthesize bar = bar_;
@synthesize baz = baz_;

#pragma mark - NSCoding

- (void)encodeWithCoder:(NSCoder *)encoder  {
    [encoder encodeObject:self.bar forKey:@"bar"];
    [encoder encodeInteger:self.baz forKey:@"baz"];
}

- (id)initWithCoder:(NSCoder *)decoder  {
    if ((self = [super init])) {
        self.bar = [decoder decodeObjectForKey:@"bar"];
        self.baz = [decoder decodeIntegerForKey:@"baz"];
    }
    return self;
}

- (void) dealloc {

    [bar_ release];
    [super dealloc];    
}

@end
于 2011-11-13T13:58:39.370 に答える