2012-02-28 37 views
6

Tôi đã cố gắng tạo bộ mã hóa và bộ giải mã chung cho các lớp mô hình của mình. Tôi đã cố gắng tìm cách gọi phương thức mã hóa " cho tất cả các loại thuộc tính, hoặc đối tượng (NSString, NSNumber, NSArray, etc ...) và các kiểu nguyên thủy. Và tôi thấy ai đó làm như sau. Và tôi đã tự hỏi nếu điều này sẽ là một cách chính xác để làm điều đó.NSCode: bộ mã hóa và bộ giải mã cho các kiểu nguyên thủy

Thuộc tính:

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

Enconder và Decoder Code:

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

Tôi đã không chắc chắn nếu điều này là một cách chính xác, hoặc nếu chương trình hoặc đối tượng khác có thể viết trong cùng một không gian bộ nhớ của các thuộc tính nguyên thủy.

Con đường tôi nghĩ là đúng::

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

Tôi đã thử nghiệm và cả hai phương pháp trả lại giá trị đúng nếu các phương pháp trên là chính xác, sự khác biệt giữa trên và đây là những gì.

+0

Tôi không hiểu. Đã có các phương pháp để mã hóa/giải mã các kiểu nguyên thủy, tại sao bạn không sử dụng chúng? Đối với tôi, phương pháp thứ hai là chính xác hơn. – Bejil

Trả lời

8

Cả hai phương pháp đều hoạt động. Đầu tiên là đặc biệt thông minh, rằng valueForKey: sẽ luôn luôn trả về một NSObject, ngay cả khi giá trị thực sự là một nguyên thủy, do đó, float/int/bool loại sẽ được bọc trong một NSNumber tự động bởi KVC getter, và unwrapped in thiết lập KVC.

Có thể sử dụng điều này để thực hiện một số chức năng mã hóa/giải mã chung hoạt động trên một mảng các khóa thuộc tính.

Tuy nhiên, ví dụ thứ hai là cách tiêu chuẩn để làm điều đó và cách tôi có thể đề xuất. Đôi khi bạn phải viết mã soạn sẵn!

+0

Tốt để biết rằng cả hai sẽ làm việc và nó là ok để sử dụng. Nhưng, tại sao bạn muốn giới thiệu cái thứ hai? Bạn có biết bất kỳ loại hiệu suất đạt được nếu bạn sử dụng phương pháp thứ hai? - Hiện tại, tôi có 2 lựa chọn để viết enconde/giải mã chung, hoặc sử dụng phương thức mã hóa đầu tiên được đăng ở trên hoặc sử dụng NSDictionary có chứa tất cả các thuộc tính nguyên thủy của tôi. Bạn sẽ giới thiệu cách nào? – lao

+0

Tôi không biết chắc chắn, nhưng tôi tin rằng sẽ có sự khác biệt về hiệu suất không đáng kể. Nếu bạn đang lưu trữ các nguyên thủy trong một NSDictionary, bạn sẽ phải chuyển đổi chúng thành NSNumbers trước khi làm như vậy anyway, do đó, nó có hiệu quả điều tương tự. Đề xuất của tôi là chỉ cần viết mã/giải mã theo cách thủ công, nhưng nếu bạn muốn thử mã hóa/giải mã chung, đầu tiên sẽ là tùy chọn tốt nhất. Tuy nhiên, nếu hiệu suất là một vấn đề lớn, bạn thực sự nên cân nhắc chuyển sang mô hình Dữ liệu cốt lõi. NSCoder khá chậm khi mã hóa cây đối tượng lớn. – joerick

+0

Vâng, tôi tưởng tượng rằng có thể là một sự khác biệt hiệu suất nhỏ là tốt. Bây giờ, tôi nghĩ rằng tôi sẽ viết bộ mã hóa/giải mã chung bằng phương pháp đầu tiên. Tôi không tin rằng nó sẽ gây ra cho tôi bất kỳ sự khác biệt lớn về hiệu suất và sẽ tiết kiệm cho tôi rất nhiều thời gian cho các dự án khác. Và vâng, tôi sẽ sử dụng mô hình Core Data cho các đối tượng lớn, tôi chỉ định dùng NSCoder cho các đối tượng prefs nhỏ. Nhưng cảm ơn! – lao

1

Phương pháp đầu tiên của bạn trông rất lạ!

Trong mục tiêu-C float/int/BOOL không phải là "Đối tượng". Bạn có thể chuyển đổi chúng thành một số điện thoại NSNumber bằng cách gọi:

Nhưng giải pháp thứ hai của bạn có vẻ ổn.
Chỉ sử dụng decodeObjectForKey cho các đối tượng như NSArray, vv hoặc lớp riêng bạn (trong đó bạn cũng cần phải thêm các phương thức mã hóa/giải mã!)

Và rời khỏi ngón tay của bạn từ setValuevalueForKey.

1

Hãy thử điều này:

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

Sau đó xuất phát từ đó lớp cơ sở lớp học của bạn với dữ liệu thực tế.

Ví dụ về lớp đơn giản:

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]; 
} 
Các vấn đề liên quan