2011-11-13 9 views
2

私は、NSObjectから継承するXYZというクラスと、XYZのオブジェクトを含む配列を持っています。私はplistファイルにこの配列を文書ディレクトリに書き込む必要があります。 [array writeToFile ....]を試した後、配列にXYZクラスのカスタムオブジェクトが含まれているため、writeToFileが失敗することが判明しました。カスタムオブジェクトを含むPlistファイルを保存するiPhone

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

答えて

9

Ray Wenderlich's blogには、NSCodingの使用方法を説明する非常に良いチュートリアルがあります。

は、単にあなただけの*を実装する必要があります - (無効)encodeWithCoder:(NSCoder をエンコードし、* - (ID)initWithCoder:(NSCoder )デコーダようなNSCodingプロトコルを尊重し、あなたのオブジェクトで方法:

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

また、公式文書hereを確認することもできます。

+0

どうもありがとう..:) – Shri

+0

メモリリークが発生しました - (id)initWithCoder:(NSCoder *)各行のデコーダ。考えられる理由を知ることができますか? (私のiVar1とivar2は文字列です) – Shri

+0

あなたはdeallocメソッドでそれらをリリースしましたか? –

0

-initWithCoder:-encodeWithCoder:の2つの方法を実装する必要があります。 NSCodingドキュメントを読む。彼らはかなり簡単な方法です。基本的には、名前に対応するキーを使用してインスタンス変数をエンコード/デコードする必要があります。

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メッセージ実装することです:カスタムクラスのためのencodeWithCoder:initWithCoder:を実装した後

#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 
9

をここにあります読み書き方法:

書き込み:

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]; 
+0

特定のオブジェクトを削除するには、どうすればいいですか? – raaz

1

NSCodingプロトコルにあなたのXYZクラスを準拠は確かにあなたがしようとしている何のために非常に適しています。これを行うには、あなたのクラスのインターフェイス宣言にNSCodingプロトコルを追加するには:とinitWithCoder:あなたの実装で

@interface XYZ <NSCoding> 

を次に、あなたはencodeWithCoderを実装する必要があります。 「コーダでエンコードする」とは、オブジェクトの現在の状態を「エンコーダ」という汎用オブジェクトにパックすることを意味します。 "コーダーで初期化"とは、 "既にパックされたエンコーダーオブジェクトが与えられ、エンコーダーにパックされたデータで自分自身を構成する"ことを意味します。これらの方法の両方で、 'エンコーダ'は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 
関連する問題