如何将类中存在的 NSMutablearray 保存到文件中?

Posted

技术标签:

【中文标题】如何将类中存在的 NSMutablearray 保存到文件中?【英文标题】:How to save NSMutablearray that is present in a class to a file? 【发布时间】:2016-10-23 00:33:17 【问题描述】:

学生.h

#import <Foundation/Foundation.h>
#import "Subject.h"

@interface Student : NSObject <NSCoding> 
    NSString *studentID;
    NSString *studentName;
    NSMutableArray<Subject* > *subjects;


@property (copy) NSString *studentID;
@property (copy) NSString *studentName;
@property (copy) NSMutableArray<Subject* > *subjects;

-(Student *)initWithStudentID:(NSString *)ID andStudentName:(NSString *)name;

-(void)addSubject:(Subject *) subject;
@end

学生.m

#import "Student.h"

@implementation Student

@synthesize  studentName;
@synthesize  studentID;
@synthesize  subjects;

-(Student *)initWithStudentID:(NSString *)ID andStudentName:(NSString *)name 

    Student *student = [[Student alloc] init];

    student.studentID = [NSString stringWithString:ID];
    student.studentName = [NSString stringWithString:name];

    return student;


-(void)addSubject:(Subject *)subject
    if(subjects==nil)
        subjects=[[NSMutableArray alloc]init];
    
    [subjects addObject:subject];




- (id)initWithCoder:(NSCoder *)aDecoder 
    if (self = [super init]) 
        [self setStudentID:[aDecoder decodeObjectForKey:@"studentID"]];
        [self setStudentName:[aDecoder decodeObjectForKey:@"studentName"]];
        [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:subjects] forKey:@"subjects"];
           
    return self;


- (void)encodeWithCoder:(NSCoder *)aCoder 
    [aCoder encodeObject:studentID forKey:@"studentID"];
    [aCoder encodeObject:studentName forKey:@"studentName"];
    [aCoder encodeObject:subjects forKey:@"subjects"];


@end

主题.h

#import <Foundation/Foundation.h>

@interface Subject : NSObject
@property  NSString *subjectID;
@property  NSString *subjectName;
@end

主题.m

#import "Subject.h"

@implementation Subject
@end

Main.m

#import <Foundation/Foundation.h>
#import "Student.h"

int main(int argc, const char * argv[]) 
    @autoreleasepool 
        Student *student1=[[Student alloc ]initWithStudentID:@"Nirmal" andStudentName:@"101"];

        Subject *subject = [Subject alloc];
        subject.subjectID=@"S01";
        subject.subjectName=@"PHY";

        [student1 addSubject:subject];

        [NSKeyedArchiver archiveRootObject:student1 toFile:@"/Users/kuzhandaivel/Documents/nirmal.plist"];

        Student *student2=[NSKeyedUnarchiver unarchiveObjectWithFile:@"/Users/kuzhandaivel/Documents/nirmal.plist"];

        NSLog(@"%@",student2.studentID);
        NSLog(@"%@",student2.studentName);
        NSLog(@"%@",[student2.subjects description]);

    
    return 0;

上面的程序在以下行抛出以下错误:

[aCoder encodeObject:subjects forKey:@"subjects"];

encodeWithCoder 函数存在于 student.m 文件中。

Archiver[4667:102276] -[Subject encodeWithCoder:]:无法识别的选择器发送到实例 0x1006000a0 2016-10-22 20:25:57.738 Archiver[4667:102276] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[Subject encodeWithCoder:]:无法识别的选择器发送到实例 0x1006000a0” *** 首先抛出调用堆栈:

【问题讨论】:

【参考方案1】:

Subject 也需要像Student 一样符合NSCoding 协议。

您要归档的根对象中存储的每个类都必须符合NSCoding 协议。

【讨论】:

@interface 主题:NSObject。我是这样添加的。我应该在 Subject.m 文件中添加 initWithCoder 和 encodeWithCoder 函数吗?请指教 是的。每个声明它符合NSCoding 协议的类都需要这两种方法。 感谢 rMaddy。我现在就试试!! 你能告诉我如何将 NSDecimalNumber 保存到文件中。对于行 --> @property NSDecimalNumber *miles,我在 initWithCoder 方法中编写 self.miles = [coder decodeObjectForKey:@"miles"] 和在 encodeWithCoder 方法中编写 [aCoder encodeObject:_miles forKey:@"miles"] 。但是数据没有保存在 plist 文件中。请指教【参考方案2】:

对象层次结构中的所有对象都需要确认 NSCoding 协议才能保存到存档。

如果你看到 NSString 类

@interface NSString : NSObject &lt;NSCopying, NSMutableCopying,NSSecureCoding>

它实现了 NSSecureCoding,它是 NSCoding 的子类。所以需要对所有的子对象和子对象的子对象等实现NSCoding协议。 它基本上遍历所有子对象并一一编码。因此,如果您没有在其中任何一个上实施,它将失败。

Archiver[4667:102276] -[Subject encodeWithCoder:]:无法识别 选择器发送到实例 0x1006000a0 2016-10-22 20:25:57.738 Archiver[4667:102276] * 由于未捕获的异常而终止应用程序 'NSInvalidArgumentException',原因:'-[Subject encodeWithCoder:]: 无法识别的选择器发送到实例 0x1006000a0' * 首先抛出调用栈:

我认为这句话说明了一切。

[主题 encodeWithCoder:(NSCoder *)aCoder]

【讨论】:

嗨,你能告诉我如何保存 NS 你能告诉我如何将 NSDecimalNumber 保存到文件中。对于行 --> @property NSDecimalNumber *miles,我在 initWithCoder 方法中编写 self.miles = [coder decodeObjectForKey:@"miles"] 和在 encodeWithCoder 方法中编写 [aCoder encodeObject:_miles forKey:@"miles"] 。但是数据没有保存在 plist 文件中。请指教 它应该可以作为 NSDecimalNumber->NSNumber->NSValue->NSObject 正常工作。这是类层次结构,它应该可以正常工作。我能说的唯一问题是,如果你在上面设置了访问器,你应该使用 self.miles 而不是 iVar。你可以试试 self.miles 并检查它是否工作?

以上是关于如何将类中存在的 NSMutablearray 保存到文件中?的主要内容,如果未能解决你的问题,请参考以下文章

如何测试 NSMutableArray 中是不是存在 _NSCFConstantString?

如何将类作为方法的参数传递? [复制]

有没有办法将类中的枚举属性设置为所有可用的枚举?

如何在 NSMutableArray 中存储 CGRect 值?

从 viewController 访问 NSObject 类中的 NSMutableArray

如何从自定义类中检索 NSArray