2

I'm exploring the idea of subclassing NSCoder to read/write a proprietary file format. I'm starting to believe this might also require me to subclass NSArray and NSDictionary to override encodeWithCoder: to ensure they are encoded properly:

- (void)encodeWithCoder:(NSCoder *)encoder {
    if ([encoder isKindOfClass:[CustomCoder class]]) {
        // call [encoder encode...] as I see fit.
    }else
        [super encodeWithCoder:encoder];
}

I'm reluctant to do this because NSCoder and its related protocols NSCoding should be self-sufficient... Requiring subclassing classes following the protocol seems like bad design. Am I missunderstanding or over-thinking something?!?

Elaborating a little:
For example, if the file format stipulates that lists of items are encoded like so:

...      // rest of file
0xA1     // marks the beginning of a list
0x0010   // amount of item in list.  The list contains 16 items in this example.
...      // encoded items follows

I would imagine that to encode an array, it's encodeWithCoder: would need to look like this:

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeValueOfObjCType:@encode(short) at:&itemCount];
    for ( /*for each item of the array*/ ) {
        [item encodeWithCoder:encoder];
    }
}

Because I ignore how NSArray's encodeWithCoder: is implement, I imagine I'd have to override it to use my NSCoder class properly.

2 Answers2

2

I don't understand why do you think you need to subclass collection classes. How your implementation will differ from default one?

At some point encodeObject: method of your NSCoder subclass will get called. In that method you can recognize NSArray and encode it as your format requires. I mean it's up to your NSCoder subclass to call encodeWithCoder: of objects it encounters or not to call and encode them somehow else.

pronvit
  • 4,169
  • 1
  • 18
  • 27
  • Elaborated the question a bit. Hopefully this will help. –  Nov 25 '11 at 18:20
  • 1
    At some point encodeObject: method of your NSCoder subclass will get called. In that method you can recognize NSArray and encode it as your format requires. – pronvit Nov 25 '11 at 19:22
  • I mean it's up to your NSCoder subclass to call encodeWithCoder: of objects it encounters or not to call and encode them somehow else. – pronvit Nov 25 '11 at 19:34
  • Very interresting!! But if I had myClass to encode with NSKeyedArchiver, the myClass's `encodeWithCoder:` would [describe itself](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Archiving/Articles/codingobjects.html) to NSKeyedArchiver (by calling things such as `encodeFloat:forKey:`). But with a custom NSCoder, you say it's the other way around?!? The coder is aware of how to encode particular classes. Interesting to have the _model describing itself to the coder_ in one scenario and _the coder being aware of the model_ in another. Do I understand this right? –  Nov 25 '11 at 20:39
  • 1
    `NSCoding` protocol with its `encodeWithCoder:` method allows coders to encode any object without knowing anything about it. But it doesn't mean coder MUST use `encodeWithCoder:` for all objects. So for all objects except `NSArray`s you can call `encodeWithCoder:` like standard coders do but for `NSArray`s write header, length and then call `encodeWithCoder:` for all objects of the array. – pronvit Nov 25 '11 at 22:32
0

Luckily for you, you will not need to subclass any collection classes such as NSArray or NSDictionary. This is because of the magic of polymorphism, the idea that the collection will encode each object individually by calling encodeWithCoder: on it. Because of this, simply implementing the NSCoder protocol on a class will be sufficient for encoding a collection that may contain instances of that class.

Alex Nichol
  • 7,512
  • 4
  • 32
  • 30
  • But if an encoded array must look like : _<8bit-Constant><16bit-ITEM-COUNT>_ (see question for the added example). How do you ensure this encoding solely with an NSCoder without subclassing NSArray? –  Nov 25 '11 at 18:36