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

相关问题