4

我已經定義了一個叫做場合的自定義對象如下:將NSMutableArray保存到NSUserDefaults的最佳方法是什麼?

#import <Foundation/Foundation.h> 


@interface Occasion : NSObject { 

NSString *_title; 
NSDate *_date; 
NSString *_imagePath;  

} 

@property (nonatomic, retain) NSString *title; 
@property (nonatomic, retain) NSDate *date; 
@property (nonatomic, retain) NSString *imagePath; 

現在我有我要保存到NSUserDefaults的場合一個NSMutableArray。我知道這是不可能的,所以我想知道哪個是最簡單的方法呢?如果序列化是答案,那麼如何?因爲我閱讀了文檔,但無法完全理解它的工作方式。

回答

11

你應該使用類似NSKeyedArchiver到數組序列化爲NSData,將它保存到NSUserDefaults,然後用NSKeyedUnarchiver以後反序列化:

NSData *serialized = [NSKeyedArchiver archivedDataWithRootObject:myArray]; 
[[NSUserDefaults standardUserDefaults] setObject:serialized forKey:@"myKey"]; 

//... 

NSData *serialized = [[NSUserDefaults standardUserDefaults] objectForKey:@"myKey"]; 
NSArray *myArray = [NSKeyedUnarchiver unarchiveObjectWithData:serialized]; 

您將需要實現你的OccasionNSCoding協議類並正確保存各種屬性以使其正確工作。欲瞭解更多信息,請參閱Archives and Serializations Programming Guide。這不應該超過幾行代碼。喜歡的東西:

- (void)encodeWithCoder:(NSCoder *)coder { 
    [super encodeWithCoder:coder]; 

    [coder encodeObject:_title forKey:@"_title"]; 
    [coder encodeObject:_date forKey:@"_date"]; 
    [coder encodeObject:_imagePath forKey:@"_imagePath"]; 
} 

- (id)initWithCoder:(NSCoder *)coder { 
    self = [super initWithCoder:coder]; 

    _title = [[coder decodeObjectForKey:@"_title"] retain]; 
    _date = [[coder decodeObjectForKey:@"_date"] retain]; 
    _imagePath = [[coder decodeObjectForKey:@"_imagePath"] retain]; 

    return self; 
} 
+0

感謝您的幫助。這個想法現在對我來說很清楚。最後一個問題:對於這個步驟(NSArray * myArray = [NSKeyedUnarchiver unarchiveObjectWithData:serialized];)會給我一個NSArray,而我的原始數組是一個NSMutableArray。所以我應該使用類似[複製可變]的東西? – Ali

+0

如果它返回一個標準的'NSArray',然後使用'[array mutableCopy]'得到一個可變的版本。 –

+0

再次感謝您的幫助。 – Ali

1

你可以在Occasion實現NSCoding

然後,您使用[NSKeyedArchiver archivedDataWithRootObject:myArray]從該數組創建一個NSData對象。你可以把它放到用戶的默認值中。

3

NSUserDefaults用於用戶偏好,不存儲應用程序數據。使用CoreData或將對象序列化到文檔目錄中。你需要讓你的班級實施NSCoding協議才能工作。

1)Occasion.h

@interface Occasion : NSObject <NSCoding> 

2實施NSCoding)在Occasion.m

- (id)initWithCoder:(NSCoder *)aDecoder { 

    if (self = [super init]) { 

     self.title = [aDecoder decodeObjectForKey:@"title"]; 
     self.date = [aDecoder decodeObjectForKey:@"date"]; 
     self.imagePath = [aDecoder decodeObjectForKey:@"imagePath"]; 

    }    
    return self; 
} 

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

    [aCoder encodeObject:title forKey:@"title"]; 
    [aCoder encodeObject:date forKey:@"date"]; 
    [aCoder encodeObject:imagePath forKey:@"imagePath"]; 
} 

3實現協議)存檔在文件目錄中的數據以一個文件

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, 
            NSUserDomainMask, YES); 
NSString *documentsPath = [paths objectAtIndex:0]; 
NSString *path= [documentsPath stringByAppendingPathComponent:@「occasions」]; 
[NSKeyedArchiver archiveRootObject:occasions toFile:path]; 

4 )要取消存檔...

NSMutableArray *occasions = [NSKeyedUnarchiver unarchiveObjectWithFile:path]; 
+0

謝謝你的回答。我的另一個問題是:我已經在Occasion對象中調用了兩個方法:( - (id)init AND - (id)initWithTitle:(NSString *)title date:(NSDate *)date imagePath:(NSString *) imagePath)現在我應該取消這兩個方法,並且每當我想要創建Occasion的新實例時都使用initWithCoder和encodeWithCoder? – Ali

+0

不,當您想創建對象時,仍然使用init或initWithTitle:date:imagePath。編碼器方法僅用於序列化。 –

+0

我明白了。再次感謝。 – Ali

相關問題