2012-02-28 19 views
6

モデルクラス用の汎用エンコーダとデコーダを作成しようとしていました。私は"エンコードメソッド"オブジェクト(NSString、NSNumber、NSArrayなど)とプリミティブ型のすべてのタイプのプロパティを呼び出す方法を見つけようとしていました。そして私は次のことをする人を見た。そしてこれが正しい方法であるかどうか疑問に思っていました。NSCode:プリミティブ型のエンコーダとデコーダ

プロパティ:

@property (assign,nonatomic) int integerP; 
@property (assign,nonatomic) float floatP; 
@property (assign,nonatomic) BOOL boolP; 

Enconderとデコーダコード:

- (void)encodeWithCoder:(NSCoder *)encoder 
{ 
    id object2 = [self valueForKey:@"integerP"]; 
    id object3 = [self valueForKey:@"floatP"]; 
    id object4 = [self valueForKey:@"boolP"]; 


    [encoder encodeObject:object2 forKey:@"integerP"]; 
    [encoder encodeObject:object3 forKey:@"floatP"]; 
    [encoder encodeObject:object4 forKey:@"boolP"]; 

    //[self setValue:[NSNumber numberWithInt:90] forKey:@"heightR"]; 

    //NSLog(@"%@",[self valueForKey:@"heightR"]); 


} 

- (id)initWithCoder:(NSCoder *)decoder 
{ 
    self = [super init]; 
    if(self != nil) 
    { 

     id object2 = [decoder decodeObjectForKey:@"integerP"]; 
     [self setValue:object2 forKey:@"integerP"]; 
     id object3 = [decoder decodeObjectForKey:@"floatP"]; 
     [self setValue:object3 forKey:@"floatP"]; 
     id object4 = [decoder decodeObjectForKey:@"boolP"]; 
     [self setValue:object4 forKey:@"boolP"]; 

    } 
    return self; 
} 

私はこれが正しい方法であるかどうかわからなかった、または他のプログラムまたはオブジェクトがで書くことができればプリミティブプロパティの同じメモリ空間。

私が正しいと思った方法:上記の方法が正しい場合には、上記とこれとの違いは何ですか

- (void)encodeWithCoder:(NSCoder *)encoder 
{ 


    [encoder encodeInt:integerP forKey:@"integerP"]; 
    [encoder encodeFloat:floatP forKey:@"floatP"]; 
    [encoder encodeBool:boolP forKey:@"boolP"]; 

    //[self setValue:[NSNumber numberWithInt:90] forKey:@"heightR"]; 

    //NSLog(@"%@",[self valueForKey:@"heightR"]); 


} 

- (id)initWithCoder:(NSCoder *)decoder 
{ 
    self = [super init]; 
    if(self != nil) 
    { 
     integerP = [decoder decodeIntForKey:@"integerP"]; 
     floatP = [decoder decodeFloatForKey:@"floatP"]; 
     boolP = [decoder decodeBoolForKey:@"boolP"]; 


    } 
    return self; 
} 

私がテストし、両方の方法は、正しい値を返していました。

+0

私は理解していません。プリミティブ型をエンコード/デコードするメソッドはすでにあります。なぜそれらを使用しないのですか?私の場合、2番目の方法がより正しいです。 – Bejil

答えて

8

どちらの方法も機能します。

第一フロート/ INT/BOOLタイプはKVCゲッターによって自動的にのNSNumberに包まれ、及びで開封されるようvalueForKey:は常に、値が実際に原始的であっても、NSObjectのを返すことであり、特に巧妙ですKVCセッター。

これを使用して、プロパティキーの配列で動作する一般的なエンコード/デコード関数を実装することができます。

しかし、2番目の例は標準的な方法ですが、おそらくそれをお勧めします。ボイラのコードを書かなければならないことがあります。

+0

両方がうまくいくことを知っていて、使用するのは大丈夫です。しかし、なぜあなたは2番目をお勧めしますか? 2番目の方法を使用すると、何らかのパフォーマンスの向上が分かりますか? - 今のところ、私は、上記の最初のエンコードメソッドを使用するか、すべての私のプリミティブプロパティを含むNSDictionaryを使用して、汎用enconde/decodeを書く2つの選択肢があります。あなたはどちらをお勧めしますか? – lao

+0

私は確かに分かりませんが、パフォーマンスの差はごくわずかです。 プリミティブをNSDictionaryに格納していた場合、NSNプリミティブをNSNumberに変換しなければならないので、それは事実上同じことです。 私はエンコード/デコードを手作業で書くだけですが、一般的なエンコード/デコードを試したい場合は、最初の方法が最適です。 しかし、パフォーマンスが大きな問題である場合は、実際にコアデータモデルに移行することを検討する必要があります。 NSCoderは大きなオブジェクトツリーをエンコードするのにかなり遅いです。 – joerick

+0

ええ、それは小さなパフォーマンスの違いかもしれないと思います。今のところ、最初の方法でジェネリックエンコーダ/デコーダを作成すると思います。私はそれが私に大きなパフォーマンスの違いを引き起こし、他のプロジェクトのために多くの時間を節約するとは思っていません。そして、私は大きなオブジェクトにCore Dataモデルを使用しますが、小さなプリファレンスオブジェクトのためにNSCoderを使用することを計画しています。しかし、ありがとう! – lao

1

あなたは最初の方法が非常に奇妙に見えます!

Objective-C float/int/BOOLでは、「オブジェクト」ではありません。

しかし、あなたの第2の解決策は、正常に見える:あなたは呼び出すことで NSNumberにそれらを変換することができます。
のみ(!あなたはまた、符号化/復号化方法を追加する必要があります)など NSArray、などのオブジェクト、または独自のクラスに

decodeObjectForKeyを使用し、setValuevalueForKeyから指を残します。

1

はこれを試してみてください:

BaseModel.h

@interface BaseModel : NSObject<NSCoding> 
@end 

BaseModel.m

- (NSArray *)keysForEncoding 
{ 
    [NSException raise:@"keysForEncoding" format:@"keysForEncoding must be implemented in child class!"]; 
    //example implementation in child class: 
    //return @[@"airtime", @"channelID", @"duration", @"programID", @"shortTitle"]; 
    return nil; 
} 


-(void)encodeWithCoder:(NSCoder *)aCoder 
{ 
    for(NSString* key in [self keysForEncoding]) 
    { 
     [aCoder encodeObject:[self valueForKey:key] forKey:key]; 
    } 
} 

-(id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super init]; 
    if (self) { 
     for (NSString* key in [self keysForEncoding]) { 
      [self setValue:[aDecoder decodeObjectForKey:key] forKey:key]; 
     } 
    } 
    return self; 
} 

そして、実際のデータとその基底クラスからクラスを派生させます。

単純なクラスの例:

EPGData.h

@interface EPGData : BaseModel 
    @property(nonatomic, assign) NSTimeInterval airtime; //date in 1970 format 
    @property(nonatomic, assign) int channelID; 
    @property(nonatomic, assign) float duration; //in seconds 
    @property(nonatomic, assign) unsigned int programID; 
    @property(nonatomic, strong) NSString* shortTitle; 
    @end 

EPGData.m

- (NSArray *)keysForEncoding; 
{ 
    return [NSArray arrayWithObjects:@"airtime", @"channelID", @"duration", @"programID", @"shortTitle", nil]; 
} 
関連する問題