在 iOS 中保存/序列化自定义对象的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5413851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:21:03  来源:igfitidea点击:

Correct way to save/serialize custom objects in iOS

iphoneios

提问by system

I have a custom object, a UIImageViewsubclass which has a few gestureRecognizerobjects.

我有一个自定义对象,一个UIImageView包含几个gestureRecognizer对象的子类。

If I have a number of these objects stored in a NSMutableArray, how would this array of objects be saved to disk so that it can be loaded when the user runs the app again?

如果我在 a 中存储了许多这样的对象NSMutableArray,如何将这个对象数组保存到磁盘,以便在用户再次运行应用程序时可以加载它?

I would like to load the array from the disk and use the objects.

我想从磁盘加载数组并使用对象。

回答by Kostas

My implementation for something similar is the following and works perfectly :

我对类似内容的实现如下并且完美运行:

The custom object (Settings) should implement the protocol NSCoding :

自定义对象(设置)应该实现协议 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;
}

The following code writes the custom object to a file (set.txt) and then restores it to the array myArray :

以下代码将自定义对象写入文件 (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]; 

回答by aroth

//store the array
[NSKeyedArchiver archiveRootObject:myArray toFile:@"someFile"];

//load the array
NSMutableArray* myArray = [NSKeyedUnarchiver unarchiveObjectWithFile:@"someFile"];

Official References.

官方参考

Note that when the array contains custom object types, you must ensure your type conforms to the NSCoding Protocolbefore this will work.

请注意,当数组包含自定义对象类型时,您必须确保您的类型符合NSCoding 协议才能工作。

回答by Greg

This blog post explains how to store an array of custom objects to disk using NSKeyedArchiverand read it back with NSKeyedUnarchiver:

这篇博文解释了如何使用NSKeyedArchiver将一组自定义对象存储到磁盘并使用NSKeyedUnarchiver读取它:

http://www.cocoabuilder.com/archive/cocoa/240775-saving-nsarray-of-custom-objects.html

http://www.cocoabuilder.com/archive/cocoa/240775-saving-nsarray-of-custom-objects.html

Apple also has a very helpful guide on the matter, the Archives and Serializations Programming Guide.

Apple 在这方面也有一个非常有用的指南,Archives and Serializations Programming Guide

回答by Denis Kutlubaev

I would like to share my improvements to Kostas solution, if somebody needs them.

如果有人需要,我想分享我对 Kostas 解决方案的改进。

  1. A class name can be used to generate text file name to store object.
  2. It is a good solution to save objects of a view controller in viewWillDisappear method and restore them in viewDidLoad method.
  3. File name should be generated in separate method to avoid duplicate code.
  4. After restoring object, it should be checked to be not nil.
  1. 类名可用于生成文本文件名来存储对象。
  2. 在 viewWillDisappear 方法中保存视图控制器的对象并在 viewDidLoad 方法中恢复它们是一个很好的解决方案。
  3. 文件名应在单独的方法中生成,以避免重复代码。
  4. 恢复对象后,应该检查它不为nil。


- (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;
}