Search code examples
objective-ckvc

Key Value Coding for `description` property - Is this completely idiotic?


I am jumping into a codebase that I'm unfamiliar with to resolve a critical crash, so I'm interested in finding a quick fix for the problem below that I can patch and come back to refactor later.

There is a strong coupling between the JSON structure returned by the web service and the Objective-C domain objects. The problem is that the JSON has a key description which is already declared as part of the NSObject protocol.

JSON:

{
    "channel" : {
        "description" : "blah",
        "mount"       : "blah",
        "status"      : "blah"
    }
}

Objective-C:

@interface ABCChannel : NSObject

@property (nonatomic , strong) NSString *description;
@property (nonatomic , strong) NSString *mount;
@property (nonatomic , strong) NSString *status;

@end

Not surprising, the parsing code uses KVC to shuttle values from JSON to ObjC instances. From what I can tell, for Swift interop Apple has changed the internals of NSObject's description from a method to a readonly property. Clang emits this:

warning: auto property synthesis will not synthesize property 'description' because it is 'readwrite' but it will be synthesized 'readonly' via another property [-Wobjc-property-synthesis]

Okay. So ,I see two options:

  1. (Preferred) Change the name of the property from description to something else. The problem is the parser will throw an exception in setValue:forKey: because of the undefined description key.

  2. Back the description property with an instance variable using @synthesize description = _channelDescription;


I see option #1 as taking a step in the direction of the inevitable future refactor, and I would like to set myself up for that, if possible. I can fix the KVC problem with ABCChannel class no longer being compliant for the description key with the following code:

- (id)valueForUndefinedKey:(NSString *)key
{
    if ([key isEqualToString:@"description"]) {
        return [self valueForKey:@"details"];
    }

    return [super valueForUndefinedKey:key];
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
    if ([key isEqualToString:@"description"]) {
        [self setValue:value forKey:@"details"];
    }
    else {
        [super setValue:value forUndefinedKey:key];
    }
}

I am wondering if this is a terrible idea that will cause problems, and if I should just back the description property with an ivar and completely address the refactor later.


Solution

  • Backing the description property with an instance variable was the safest bet, especially for consistency across iOS 7 and iOS 8.