2009-11-09 45 views
4

我正在開發iphone應用程序。如何使用NSCoder

我使用NSCoder。

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

#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 

但WARNNING。

'NSCoder' may not respond to '-decodeDataObjectForKey' 

如何使用NSCoder?

回答

2

,我認爲你應該使用-decodeObjectForKey:

3

這是來自我的LogEntry對象的NSCoding協議方法,雖然可以忽略switch語句和模式細節,但它們來自於我編寫的基類,它允許我保持對變化的數據格式的正常跟蹤。

請注意,除了使用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]; 
} 
+3

任何需要提醒的是誰保留或複製這些對象也需要一個鏈接到內存管理規則:http://developer.apple.com/mac/library/documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html – 2009-11-09 16:07:17

+0

添加了正在編寫的源代碼。這是問題嗎? – marcy 2009-11-10 07:00:14

+0

我在您發佈的代碼中看到的最大問題是您不保留從編碼器中檢索的值。 – 2009-11-12 16:20:47

0

我寫了一個使用NSCoding的幫助函數。它是VSCore Library的一部分。看看這裏:

@interface QuickCoding : NSObject 

+ (void)quickEncode:(NSObject<NSCoding>*)object withEncoder:(NSCoder*)encoder; 
+ (void)quickDecode:(NSObject<NSCoding>*)object withDecoder:(NSCoder*)decoder; 

@end 

與.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 

全部代碼是在這裏:https://github.com/voipswitch/VSCore/tree/master/VSCore/Storage