2

Summary: When I derive a custom class from an <NSCoding> parent, I see my encodeWithCoder method called during application state preservation. If I change my parent to SKNode, my encodeWithCoder method is no longer called.

Details:

My view controller gets encoded during UIKit application state preservation. It encodes a single object of type MyNode.

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
  [super encodeRestorableStateWithCoder:coder];

  MyNode *myNode = [[MyNode alloc] init];
  NSLog(@"view controller encoding");
  [coder encodeObject:myNode forKey:@"myNode"];
}

MyNode is a stripped-down class built for this question. I'll include the code for completeness, but the encode and decode methods merely call NSLog and super.

@interface MyParent : NSObject <NSCoding>
@end

@interface MyNode : MyParent
@end
@implementation MyParent

- (id)initWithCoder:(NSCoder *)aDecoder
{
  NSLog(@"MyParent decoding");
  self = [super init];
  return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
  NSLog(@"MyParent encoding");
}

@end

@implementation MyNode

- (id)initWithCoder:(NSCoder *)aDecoder
{
  NSLog(@"MyNode decoding");
  self = [super initWithCoder:aDecoder];
  return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
  NSLog(@"MyNode encoding");
  [super encodeWithCoder:aCoder];
}

@end

When the parent of MyNode is MyParent, as written above, then I see my logged output during application preservation:

2014-05-12 15:22:33.342 Flippy[35091:60b] saving application state
2014-05-12 15:22:33.342 Flippy[35091:60b] view controller encoding
2014-05-12 15:22:33.343 Flippy[35091:60b] MyNode encoding
2014-05-12 15:22:33.343 Flippy[35091:60b] MyParent encoding

But when I change the parent of MyNode to SKNode, then my encodeWithCoder implementations are not called:

2014-05-12 15:22:57.847 Flippy[35115:60b] saving application state
2014-05-12 15:22:57.848 Flippy[35115:60b] view controller encoding

Why not?

Things I have tried:

  • Archiving my custom class using my own NSKeyedArchiver. This works as expected.
  • Implementing UIStateRestoring protocol on my custom class, and registering it with the application with a restoration identifier. This didn't make much sense to me.
  • Messing with classForCoder, as in this question. But it doesn't sound like it applies, and classForCoder is not getting called on my custom class anyway.

(The details of my real-world problem that inspired this test case don't seem relevant.)

Community
  • 1
  • 1
Karl Voskuil
  • 750
  • 6
  • 19
  • 1
    I had answered it was because `SKNode` doesn't implement `NSCoding`. Karl pointed out (correctly): "Good thought, but `SKNode` does implement `NSCoding` (see `SKNode` Class Reference). Also, the way message handling works, even if `MyNode` didn't declare that it conformed to ``, it would still try to handle the `encodeWithCoder` message." I have removed my answer because people might ignore the question since it already has an answer. – vacawama May 13 '14 at 13:12
  • For what it's worth, I'm working on a new app and running into the same problem, and it still boggles me: What is happening in `NSKeyedArchiver encodeObject:forKey:` that can prevent the object's `encodeWithCoder:` method from being called, and what is `SKNode` doing to prevent such a thing? The answer must be in the source code. – Karl Voskuil Mar 09 '16 at 21:29

0 Answers0