在 iOS 中保存/序列化自定义对象的正确方法
Posted
技术标签:
【中文标题】在 iOS 中保存/序列化自定义对象的正确方法【英文标题】:Correct way to save/serialize custom objects in iOS 【发布时间】:2011-03-24 01:46:33 【问题描述】:我有一个自定义对象,一个 UIImageView
子类,它有几个 gestureRecognizer
对象。
如果我在NSMutableArray
中存储了许多这样的对象,如何将这些对象数组保存到磁盘,以便在用户再次运行应用程序时可以加载它?
我想从磁盘加载数组并使用对象。
【问题讨论】:
【参考方案1】:我对类似的实现如下,并且效果很好:
自定义对象(设置)应该实现协议 NSCoding :
-(void)encodeWithCoder:(NSCoder *)encoder
[encoder encodeObject:self.difficulty forKey:@"difficulty"];
[encoder encodeObject:self.language forKey:@"language"];
[encoder encodeObject:self.category forKey:@"category"];
[encoder encodeObject:self.playerType forKey:@"playerType"];
- (id)initWithCoder:(NSCoder *)decoder
if (self = [super init])
self.difficulty = [decoder decodeObjectForKey:@"difficulty"];
self.language = [decoder decodeObjectForKey:@"language"];
self.category = [decoder decodeObjectForKey:@"category"];
self.playerType = [decoder decodeObjectForKey:@"playerType"];
return self;
以下代码将自定义对象写入文件(set.txt),然后将其恢复到数组 myArray:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:@"set.txt"];
NSMutableArray *myObject=[NSMutableArray array];
[myObject addObject:self.settings];
[NSKeyedArchiver archiveRootObject:myObject toFile:appFile];
NSMutableArray* myArray = [NSKeyedUnarchiver unarchiveObjectWithFile:appFile];
【讨论】:
这应该有更多的选票。完整的解决方案,真的帮助了我。谢谢! 仅供参考:只要您的自定义对象符合NSCoding
并实现initWithCoder:
和encodeWithCoder:
,您就可以在归档时将其用作根对象。无需像此代码中那样将其放在NSMutableArray
中。
仅供参考:如果您想了解更多关于 NSKeyedArchiver 和 NSCoding 的方式、时间和原因的信息,请查看nshipster.com/nscoding。
确保您是否正在编码和解码像 NSUIntegers 这样的项目来处理 NSCoding,如下所示: self.versionNum = [[decoder decodeObjectForKey:@"versionNum"] unsignedIntegerValue];和 [encoder encodeObject:[NSNumber numberWithUnsignedInteger:self.versionNum] forKey:@"versionNum"];
应该if (self = [super init])
是if (self = [super initWithCoder:decoder])
?【参考方案2】:
//store the array
[NSKeyedArchiver archiveRootObject:myArray toFile:@"someFile"];
//load the array
NSMutableArray* myArray = [NSKeyedUnarchiver unarchiveObjectWithFile:@"someFile"];
Official References.
请注意,当数组包含自定义对象类型时,您必须确保您的类型符合 NSCoding Protocol 才能生效。
【讨论】:
谢谢。所以这应该返回保存时的数组,不管数组中有什么?数组项是否可以检索和使用? 我可能只是做错了,但我认为这种简单的代码不适用于自定义对象,两种方法都返回“否”。 @Deco - 自定义对象类型必须与 NSCoding Protocol 确认才能正常工作。【参考方案3】:这篇博文解释了如何使用NSKeyedArchiver 将自定义对象数组存储到磁盘并使用NSKeyedUnarchiver 将其读回:
http://www.cocoabuilder.com/archive/cocoa/240775-saving-nsarray-of-custom-objects.html
Apple 也有一个非常有用的指南,Archives and Serializations Programming Guide。
【讨论】:
【参考方案4】:如果有人需要,我想分享我对 Kostas 解决方案的改进。
-
类名可用于生成文本文件名来存储对象。
在 viewWillDisappear 方法中保存视图控制器的对象并在 viewDidLoad 方法中恢复它们是一个很好的解决方案。
文件名应以单独的方法生成以避免重复代码。
恢复对象后,应检查不为零。
- (void)viewDidLoad
[super viewDidLoad];
// Restoring form object from the file
NSString *formFilePath = [self formFilePath];
RRCreateResumeForm *form = [NSKeyedUnarchiver unarchiveObjectWithFile:formFilePath];
if (form != nil)
self.formController.form = form;
- (void)viewWillDisappear:(BOOL)animated
[super viewWillDisappear:animated];
// Saving the form object to the file
NSString *formFilePath = [self formFilePath];
[NSKeyedArchiver archiveRootObject:self.formController.form toFile:formFilePath];
// Returns a file path to the file with stored form data for form controller
- (NSString *)formFilePath
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *formClassName = NSStringFromClass( [self.formController.form class] );
NSString *formFileName = [NSString stringWithFormat:@"%@.txt", formClassName];
NSString *formFilePath = [documentsDirectory stringByAppendingPathComponent:formFileName];
return formFilePath;
【讨论】:
以上是关于在 iOS 中保存/序列化自定义对象的正确方法的主要内容,如果未能解决你的问题,请参考以下文章