将NSMutableArray保存到NSUserDefaults的最佳方法是什么?
我已经定义了一个叫做场合的自定义对象如下:将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。我知道这是不可能的,所以我想知道哪个是最简单的方法呢?如果序列化是答案,那么如何?因为我阅读了文档,但无法完全理解它的工作方式。
你应该使用类似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];
您将需要实现你的Occasion
的NSCoding
协议类并正确保存各种属性以使其正确工作。欲了解更多信息,请参阅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;
}
你可以在Occasion
实现NSCoding
。
然后,您使用[NSKeyedArchiver archivedDataWithRootObject:myArray]
从该数组创建一个NSData
对象。你可以把它放到用户的默认值中。
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];
谢谢你的回答。我的另一个问题是:我已经在Occasion对象中调用了两个方法:( - (id)init AND - (id)initWithTitle:(NSString *)title date:(NSDate *)date imagePath:(NSString *) imagePath)现在我应该取消这两个方法,并且每当我想要创建Occasion的新实例时都使用initWithCoder和encodeWithCoder? – Ali
不,当您想创建对象时,仍然使用init或initWithTitle:date:imagePath。编码器方法仅用于序列化。 –
我明白了。再次感谢。 – Ali
感谢您的帮助。这个想法现在对我来说很清楚。最后一个问题:对于这个步骤(NSArray * myArray = [NSKeyedUnarchiver unarchiveObjectWithData:serialized];)会给我一个NSArray,而我的原始数组是一个NSMutableArray。所以我应该使用类似[复制可变]的东西? – Ali
如果它返回一个标准的'NSArray',然后使用'[array mutableCopy]'得到一个可变的版本。 –
再次感谢您的帮助。 – Ali