2012-02-24 136 views
0

我試圖將我的對象圖保存到一個文件,然後在稍後重新加載它,但是decodeObjectForKey:對於我指定的任何鍵總是返回nil。decodeObjectForKey:總是返回零

創建了一個二進制文件,它偶爾還有人類可讀的文本,即titleTextColor,所以我認爲歸檔過程正在工作。

我想知道NSKeyedArchiver和NSKeyedUnarchiver的工作原理嗎?任何幫助,將不勝感激。

- (void)encodeWithCoder:(NSCoder *)encoder { 
    [encoder encodeFloat:titleFontSize forKey:@"titleFontSize"]; 
    [encoder encodeObject:[UIColor orangeColor] forKey:@"titleTextColor"]; 
    [encoder encodeObject:lineSeparatorColor forKey:@"lineSeparatorColor"]; 
    [encoder encodeObject:bodyTextColor forKey:@"bodyTextColor"]; 
    [encoder encodeFloat:bodyTextFontSize forKey:@"bodyTextFontSize"]; 
    [encoder encodeObject:backgroundColor forKey:@"backgroundColor"]; 
    [encoder encodeObject:tintColor forKey:@"tintColor"]; 
    [encoder encodeInteger:bodyTextAlignment forKey:@"bodyTextAlignment"]; 

    [encoder encodeObject:@"Text" forKey:@"Text"]; 
} 

+ (void) saveToFile { 
    // Get the shared instance 
    PSYDefaults *sharedInstance = [PSYDefaults sharedInstance];  

    // Serialise the object 
    NSData *serializedObject = [NSKeyedArchiver archivedDataWithRootObject:sharedInstance]; 

    // Get the path and filename of the file 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *pathAndFileName = [documentsDirectory stringByAppendingPathComponent:ksDefaultsFileName]; 

    // Write the defaults to a file 
    if (serializedObject) [serializedObject writeToFile:pathAndFileName atomically:YES]; 
} 

+ (void) loadFromFile { 
    // Get the shared instance 
    PSYDefaults *sharedInstance = [PSYDefaults sharedInstance];  

    // Get the path and filename of the file 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *pathAndFileName = [documentsDirectory stringByAppendingPathComponent:ksDefaultsFileName]; 

    NSData *codedData = [[[NSData alloc] initWithContentsOfFile:pathAndFileName] autorelease]; 
    NSKeyedUnarchiver *defaults = [[NSKeyedUnarchiver alloc] initForReadingWithData:codedData]; 

    // Set the properties of the shared instance 
    NSString *test = [defaults decodeObjectForKey:@"Text"]; 
    NSLog (@"%@", test); 
    sharedInstance.titleTextColor = [defaults decodeObjectForKey:@"titleTextColor"]; 

    [defaults release]; 
} 

編輯:根據意見從DarkDust:

- (id)initWithCoder:(NSCoder *)aDecoder { 
    self = [super init]; 
    if (self) { 
     self.titleFontSize = [[aDecoder decodeObjectForKey:@"titleFontSize"] floatValue]; 
     self.titleTextColor = [aDecoder decodeObjectForKey:@"titleTextColor"]; 
     self.lineSeparatorColor = [aDecoder decodeObjectForKey:@"lineSeparatorColor"]; 
     self.bodyTextColor = [aDecoder decodeObjectForKey:@"bodyTextColor"]; 
     self.bodyTextFontSize = [[aDecoder decodeObjectForKey:@"bodyTextFontSize"] floatValue]; 
     self.backgroundColor = [aDecoder decodeObjectForKey:@"backgroundColor"]; 
     self.tintColor = [aDecoder decodeObjectForKey:@"tintColor"]; 
     self.bodyTextAlignment = [[aDecoder decodeObjectForKey:@"bodyTextAlignment"] intValue]; 
    } 
    return self; 
} 

,只是測試創建一個新的實例:

+ (void) loadFromFile { 
    // Get the shared instance 
    PSYDefaults *sharedInstance = [PSYDefaults sharedInstance];  

    // Get the path and filename of the file 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *pathAndFileName = [documentsDirectory stringByAppendingPathComponent:ksDefaultsFileName]; 

    NSData *codedData = [[[NSData alloc] initWithContentsOfFile:pathAndFileName] autorelease]; 
    PSYDefaults *newInstance = [NSKeyedUnarchiver unarchiveObjectWithData:codedData]; 

    sharedInstance.titleTextColor = newInstance.titleTextColor; 
} 

編輯 - 更新(需要編碼花車和ints as NSNumbers)

- (void)encodeWithCoder:(NSCoder *)encoder { 
    [encoder encodeObject:[NSNumber numberWithFloat:titleFontSize] forKey:@"titleFontSize"]; 
    [encoder encodeObject:titleTextColor forKey:@"titleTextColor"]; 
    [encoder encodeObject:lineSeparatorColor forKey:@"lineSeparatorColor"]; 
    [encoder encodeObject:bodyTextColor forKey:@"bodyTextColor"]; 
    [encoder encodeObject:[NSNumber numberWithFloat:bodyTextFontSize] forKey:@"bodyTextFontSize"]; 
    [encoder encodeObject:backgroundColor forKey:@"backgroundColor"]; 
    [encoder encodeObject:tintColor forKey:@"tintColor"]; 
    [encoder encodeObject:[NSNumber numberWithInt:bodyTextAlignment] forKey:@"bodyTextAlignment"]; 
} 

回答

6

使用單個根對象序列化的數據進行解碼,但您嘗試使用不在該水平存在的一鍵反序列化。

你想unarchiveObjectWithData:,如:

NSData *codedData = [[[NSData alloc] initWithContentsOfFile:pathAndFileName] autorelease]; 
PSYDefaults *decodedDefaults = [NSKeyedUnarchiver unarchiveObjectWithData:codedData]; 

請注意,您還需要實現initWithCoder:作爲對口encodeWithCoder:。儘管看起來你想在這裏有一個單身人士,NSCoding要求在[NSKeyedArchiver archivedDataWithRootObject:sharedInstance]之前創建一個新對象。

,而無需創建的PSYDefaults一個新的實例。如果你想EN /解碼領域,那麼你需要使用-[NSKeyedArchiver initForWritingWithMutableData:]和存檔傳遞給類似的方法你encodeWithCoder:(但你應該給它一個不同的名稱,然後)。然後你會寫一個對方,通過NSKeyedUnarchiver讀取字段,在那裏你使用decodeObjectForKey:和每個字段的朋友。

您也可能想要閱讀Apple的Archives and Serializations Programming Guide

+0

這是很好的建議,謝謝。我意識到我的愚蠢與unarchiving,現在創建一個新的實例,並實施了一個initWithCoder。我認爲我快到了,當NSKeyedUnarchiver取消存檔我的對象圖時,initWithCoder被調用。然而,我在調用initWithCoder之後遇到任何問題? Dave – 2012-02-24 10:10:18

+0

Doh,擦洗。當它已經自動發佈時釋放newInstance是問題。感謝你的幫助!戴夫 – 2012-02-24 10:14:14

1

嘗試使用,以節省您的對象:

[NSKeyedArchiver archiveRootObject:object toFile:filePath]; 

,並使用加載:

[NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; 

我用上面的方法與自定義對象保存的NSDictionary到一個文件中。

而且你應該在你的對象中有函數initWithCoder:(NSCoder *)解碼器。 使用哪個

[decoder decodeObjectFoyKey:yourKey]; 
+0

謝謝Hanon,DarkDust在最後排序。給你的答案+1的幫助。 – 2012-02-24 10:17:45

0

我有另一個問題NSCoder'sdecodeObjectForKey方法,而使用FXForm - 它崩潰沒有任何解釋。

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

原因是內存問題。通常,看起來像沒有日誌中的錯誤解釋,這意味着,這是一個內存問題。我忘了使用正確的屬性 - 複製。我用assign來代替。這是正確的代碼:

@interface MyClass : : NSObject <FXForm, NSCoding> 

@property (nonatomic, copy) SomeClass *someObject; 

@end 

以防萬一有人遇到這個問題了。