Как сохранить NSMutableArray, присутствующий в классе, в файл?

#ios #objective-c

#iOS #objective-c

Вопрос:

Student.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
  

Student.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
  

Subject.h

 #import <Foundation/Foundation.h>

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

Subject.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;
}
  

Как сохранить NSMutableArray, присутствующий в классе, в файл?
Вышеупомянутая программа выдает приведенную ниже ошибку в строке:

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

encodeWithCoder функция at присутствует в файле student.m.

Архиватор [4667:102276] -[Subject encodeWithCoder:]: нераспознанный селектор, отправленный экземпляру 0x1006000a0
2016-10-22 20:25:57.738 Архиватор [4667:102276] *** Завершение работы приложения из-за неперехваченного исключения 'NSInvalidArgumentException', причина: '-[Subject encodeWithCoder:]: нераспознанный селектор, отправленный экземпляру 0x1006000a0'
*** Первый стек вызовов throw:

Ответ №1:

Subject также должно соответствовать NSCoding протоколу точно так же, как Student .

Каждый класс, хранящийся в корневом объекте, который вы архивируете, должен соответствовать NSCoding протоколу.

Комментарии:

1. @тема интерфейса: NSObject<NSCoding>. Я добавил таким образом. должен ли я добавить функции initWithCoder и encodeWithCoder в файл Subject.m? Пожалуйста, посоветуйте

2. ДА. Два метода требуются для каждого класса, который заявляет, что он соответствует NSCoding протоколу.

3. Спасибо за rMaddy. Я попробую это сейчас!!

4. Не могли бы вы, пожалуйста, сказать мне, как сохранить NSDecimalNumber в файл. Для строки —> @property NSDecimalNumber *miles я пишу как self.miles = [кодировщик decodeObjectForKey:@»miles»] в методе initWithCoder и [Кодировщик encodeObject:_miles forKey:@»miles»] в методе encodeWithCoder. Но данные не сохраняются в файле plist. Пожалуйста, посоветуйте

Ответ №2:

Все объекты внутри вашей иерархии объектов должны подтвердить протокол NSCoding, чтобы иметь возможность сохранять в архив.

Если вы видите класс NSString

@interface NSString : NSObject <NSCopying, NSMutableCopying,NSSecureCoding >

Он реализует NSSecureCoding, который является подклассом NSCoding. Итак, вам нужно реализовать протокол NSCoding для всех дочерних объектов и дочернего объекта дочернего объекта и так далее. В основном он перебирает все дочерние объекты и кодирует их один за другим. Таким образом, произойдет сбой, если вы не внедрили ни в одном из них.

Архиватор [4667: 102276] -[Subject encodeWithCoder:]: нераспознанный селектор, отправленный экземпляру 0x1006000a0 2016-10-22 20:25:57.738 Архиватор [4667:102276] * Завершение работы приложения из-за неперехваченного исключения ‘NSInvalidArgumentException’, причина: ‘-[Subject encodeWithCoder:]: нераспознанный селектор, отправленный экземпляру 0x1006000a0’ * Стек вызовов первого броска:

Я думаю, что в этой строке сказано все.

[тема encodeWithCoder:(NSCoder *)aCoder]

Комментарии:

1. Привет, не могли бы вы, пожалуйста, рассказать мне, как сохранить NS

2. Не могли бы вы, пожалуйста, сказать мне, как сохранить NSDecimalNumber в файл. Для строки —> @property NSDecimalNumber *miles я пишу как self.miles = [кодировщик decodeObjectForKey:@»miles»] в методе initWithCoder и [Кодировщик encodeObject:_miles forKey:@»miles»] в методе encodeWithCoder. Но данные не сохраняются в файле plist. Пожалуйста, посоветуйте

3. Он должен нормально работать как NSDecimalNumber-> NSNumber-> NSValue-> NSObject. Это иерархия классов, и она должна работать нормально. Единственное, что меня беспокоит, это то, что вам следует использовать self.miles, а не iVar, если вы установили средства доступа поверх него. Можете ли вы попробовать self.miles и проверить, работает ли он?