在 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 中保存/序列化自定义对象的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

iOS 对象的归档

使自定义 .NET 异常可序列化的正确方法是啥?

Django:使用自定义保存方法更新表单中的对象

Qt中 使用Json 对自定义对象进行序列与反序列化 之二

ios中解决自定义tabbar跳转隐藏问题的方法

java 为了实现自定义对象的序列化,该自定义对象必须实现哪个接口