简体   繁体   English

将Array保存到包含自定义对象iPhone的Plist文件

[英]Saving Array to Plist file that contains Custom Objects iPhone

I have a class called XYZ inheriting from NSObject and an array which contains objects of XYZ. 我有一个名为XYZ的类继承自NSObject和一个包含XYZ对象的数组。 I need to write this array to a plist file on to documents directory. 我需要将此数组写入文档目录中的plist文件。 After trying [array writeToFile....], I found that writeToFile fails because the array contains custom objects of XYZ class. 在尝试[array writeToFile ....]后,我发现writeToFile失败,因为该数组包含XYZ类的自定义对象。

The possible solution to this is to convert the objects to NSData. 可能的解决方案是将对象转换为NSData。 What are the different ways of achieving this?? 有什么不同的方法来实现这一目标? I found that NSCoding is suitable but cant understand how to use it. 我发现NSCoding很合适,但无法理解如何使用它。 Any help will be greatly appreciated. 任何帮助将不胜感激。

There is a very good tutorial on the Ray Wenderlich's blog which explains how to work with the NSCoding. Ray Wenderlich的博客上有一个非常好的教程,解释了如何使用NSCoding。

Simply you just have to implement the *-(void)encodeWithCoder:(NSCoder )encode and *-(id)initWithCoder:(NSCoder )decoder methods in your object that respects the NSCoding protocol like that: 只需要在你的对象中实现* - (void)encodeWithCoder:(NSCoder )编码和* - (id)initWithCoder:(NSCoder )解码器方法,就像那样尊重NSCoding协议:

// Header
@interface AnObject: NSObject <NSCoding>

// Implementation
- (void) encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:ivar1 forKey:@"ivar1"];
    [encoder encodeFloat:ivar2 forKey:@"ivar2"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [super initWithCoder:coder];
    ivar1 = [[coder decodeObjectForKey:@"ivar1"] retain];
    ivar2 = [[coder decodeObjectForKey:@"ivar2"] retain];
    return self;
}

You can also check the official documentation here . 您也可以在此处查看官方文档。

After implementing encodeWithCoder: and initWithCoder: for the custom class here is how to write and read: 实现encodeWithCoder:initWithCoder:对于自定义类,这里是如何写和读:

Write: 写:

NSError  *error;
NSData* archiveData = [NSKeyedArchiver archivedDataWithRootObject:yourClassInstance];
[archiveData writeToFile:filePath options:NSDataWritingAtomic error:&error];

Read: 读:

NSData *archiveData = [NSData dataWithContentsOfFile:filePath];
YourClass *yourClassInstance = (NSArray*)[NSKeyedUnarchiver unarchiveObjectWithData:archiveData];

Conforming your XYZ class to the NSCoding protocol is indeed very suitable for what you're trying to do. 使您的XYZ类符合NSCoding协议确实非常适合您要做的事情。 To do so, add the NSCoding protocol to your class's interface declaration: 为此,请将NSCoding协议添加到类的接口声明中:

@interface XYZ <NSCoding>

Then, you need implement encodeWithCoder: and initWithCoder: in your implementation. 然后,您需要在您的实现中实现encodeWithCoder:和initWithCoder :. "Encode with coder" means "take your object's current state, and pack it into a generic object called an 'encoder'". “用编码器编码”意味着“获取对象的当前状态,并将其打包成称为'编码器'的通用对象”。 "Init with coder" means "given an already-packed encoder object, configure yourself with the data packed into the encoder". “使用编码器初始化”意味着“给定已经打包的编码器对象,使用打包到编码器中的数据进行自我配置”。 In both of these methods, the 'encoder' will be an instance of NSCoder , which has a fairly simple interface for encoding ("packing") and decoding ("unpacking") basic types. 在这两种方法中,'编码器'将是NSCoder的一个实例,它具有用于编码(“打包”)和解码(“解包”)基本类型的相当简单的接口。

Here's a sample implementation: 这是一个示例实现:

@implementation XYZ
- (id)initWithCoder:(NSCoder*)encoder
{
    self = [self init];

    if (self)
    {
        self.myIntProperty = [encoder decodeIntForKey:@"myInt"];
    }

    return self;
}

– (void)encodeWithCoder:(NSCoder*)decoder
{
    [decoder encodeInt:self.myIntProperty forKey:@"myInt"];
}

@end

You need to implement two methods: -initWithCoder: and -encodeWithCoder: . 你需要实现两个方法: -initWithCoder:-encodeWithCoder: Read the NSCoding docs; 阅读NSCoding文档; they're pretty straight-forward methods. 他们是非常简单的方法。 You basically want to encode/decode your instance variables with a key that corresponds to its name. 您基本上希望使用与其名称对应的键对您的实例变量进行编码/解码。

It's pretty straight forward. 这很直接。 For given class Foo : 对于给定的类Foo

#import <Foundation/Foundation.h>

@interface Foo : NSObject <NSCoding> {
    NSArray* bar_;
    NSUInteger baz_;
}

@property (nonatomic, retain) NSArray *bar;
@property (nonatomic, assign) NSUInteger baz;

@end

All you have to do to conform to the NSCoding protocol is to implement the initWithCoder: and decodeWithCoder messages: 要符合NSCoding协议,您只需要实现initWithCoder:decodeWithCoder消息:

#import "Foo.h"

@implementation Foo
@synthesize bar = bar_;
@synthesize baz = baz_;

#pragma mark - NSCoding

- (void)encodeWithCoder:(NSCoder *)encoder  {
    [encoder encodeObject:self.bar forKey:@"bar"];
    [encoder encodeInteger:self.baz forKey:@"baz"];
}

- (id)initWithCoder:(NSCoder *)decoder  {
    if ((self = [super init])) {
        self.bar = [decoder decodeObjectForKey:@"bar"];
        self.baz = [decoder decodeIntegerForKey:@"baz"];
    }
    return self;
}

- (void) dealloc {

    [bar_ release];
    [super dealloc];    
}

@end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM