0

I am working on challenges from iOS Big Nerd Ranch book of 12th chapter and there is a problem of saving an array of items to the disk. I have BNRDrawView UIView that has an array finishedLines that holds items BNRLine defined by me. I want to use NSCoder for the purpose. So, I implemented inside BNRDrawView two methods:

- (void) encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:_finishedLines forKey:finishedLinesKey];
}

- (id)initWithCoder:(NSCoder *)decoder {

self = [super initWithCoder:decoder];

if (self) {
    _finishedLines = [decoder decodeObjectForKey:finishedLinesKey];
}
    return self;
}

and trying to save finishedLines array whenever it is changed like this:

[NSKeyedArchiver archiveRootObject:self.finishedLines
                            toFile:self.finishedLinesPath];

Loading I am trying to do inside initWithFrame BNRDrawView method:

- (instancetype)initWithFrame:(CGRect)r
{
...
self.finishedLinesPath = @"/Users/nikitavlasenko/Desktop/XCodeProjects/MyFirstApp/TouchTracker/savedLines/finishedLines";
    BOOL fileExists = [[NSFileManager defaultManager]
                       fileExistsAtPath:self.finishedLinesPath];
    if (fileExists) {
        self.finishedLines = [NSKeyedUnarchiver
                              unarchiveObjectWithFile:self.finishedLinesPath];
    }
...

It gives me the error:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[BNRLine encodeWithCoder:]: unrecognized selector sent to instance 0x7fbd32510c40'

From here I have two questions:

  1. Do I need to implement encodeWithCoder: and initWithCoder: for ALL of the classes - let's suppose that I have a plenty of different ones, defined by me - that are inside my array that I am trying to save?
  2. If you look above to my initWithCoder: method, you can see that I need to call [super initWithCoder:decoder], but do I also need to call BNRDrawView's initializer method initWithFrame: there?
Nikita Vlasenko
  • 4,004
  • 7
  • 47
  • 87

1 Answers1

2
  1. Yes, you need to implement NSCoder in all objects that are stored inside the array.

  2. No, you don't need to call initWithFrame - initWithCoder is sufficient.

Aderstedt
  • 6,301
  • 5
  • 28
  • 44