André Fratelli
André Fratelli

Reputation: 6068

- initWithCoder: when -decodeObjectOfClass:forKey: returns nil

I'm wondering how to use NSSecureCoding when a given property was nil when encoded. Take the following example:

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];

    if (self) {

        _buffer = [aDecoder decodeObjectOfClass:[NSMutableData class] forKey:@"buffer"];

        if (_buffer == nil) {
            self = nil;
        }
    }

    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder setValue:_buffer forKey:@"buffer"];
}

I created the habit of setting self to nil whenever an allocation fails, as it seems like a correct pattern. However, in this case, if _buffer was nil when encoded, how can I tell that from allocation failure when decoding?

Upvotes: 1

Views: 713

Answers (2)

junjie
junjie

Reputation: 7966

It's been a while since you asked this question. But in case anyone else is still interested to find a solution…

For NSData / NSMutableData, one idea on how to differentiate whether nil as returned by decodeObjectOfClass:forKey: is a result of failing isKindOfClass: checks, versus whether it was actually nil when during encodeWithCoder:, could be to encode [NSData data] if it was indeed nil during encoding.

For example:

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:_buffer ?: [NSMutableData data] forKey:@"buffer"];
}

Upvotes: 0

Cooper Buckingham
Cooper Buckingham

Reputation: 2534

I'm not sure of the pattern you're trying to handle here, but using setValue: directly on the coder I suspect is odd. I've only ever used, and seen, the encode<SomeThing>: forKey: syntax used. And from what I'm looking at, then trying to decode for that same key is going to result in a bad output.

But you're saying you want to distinguish between a resulting decode that is actually null, and a failure state where you've chosen to return a null value? I'm still not sure why you are handling it that way, but the only way to distinguish would be to choose a different value to store like "The Buffer has a nil value" and then checking for that string on decode, or storing a second key on the coder that you would check against:

if(_buffer == nil){
  [aCoder encodeBool: true forKey: @"wasBufferNull"];
}

Upvotes: 2

Related Questions