Question

I am using Key-Value Coding to simplify updating instances of a model class:

@interface NewsItem : NSObject 
{

}

@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *description;
@property (nonatomic, copy) NSString *link;
@property (nonatomic, copy) NSString *date;

using:

SEL selectorName = NSSelectorFromString(elementName);
if ([self.newsItem respondsToSelector:selectorName])
{
    NSString *sanitisedElement = [self sanitiseElement:self.currentElementData];
   [self.newsItem setValue:sanitisedElement forKey:elementName];
}

This works well but the 'description' property doesn't 'smell' right to me as it has overridden the base NSObject description getter (+ (NSString *)description). If the description getter is invoked now it will return irrelevant information when the caller would be expecting a description of the class.

Is it possible to safely proceed with Key-Value Coding for this class (given that I am bound to these property names by the external data source)? Or would it be wise to change the property names and manually check keys/set values instead?

Was it helpful?

Solution

You could override description in your class. This method is usually used only for debugging and no caller can expect a specific output of that method.

But I see more general problems in your code. It is only checked that a method with the given name exists. This does not imply that this method corresponds to a property, and even then, it does not imply that there is a setter for that property.

For example, every NSObject responds to the selector "init", so if the external data source sends that key as "elementName", your code would immediately crash.

Therefore, an explicit list of "known keys" is needed. But then you can as well use a mapping (NSDictionary) from external element names to internal properties to avoid any conflicts.

OTHER TIPS

I think that you are confusing methods with properties, and you are making things more complicated that how they are.

Is enough that, given an elementName that contains directly the setter name (i.e.: setDate), you invoke the selector passing that argument the object argument:

SEL selectorName = NSSelectorFromString(elementName); // elementName something like "setDate"
if ([self.newsItem respondsToSelector:selectorName])
{
    [self.newsItem performSelector: selectorName withObject: sanitisedElement];
}

As for the description method, it has overridden NSObject's description, so you have two choices: name it in another way, or leave it like it is, and invoke it on super when you need the object description, with the help of Objective-C runtime:

struct objc_super superclass= { self.newItem, [self.newItem superclass] };
NSString* desc= objc_msgSendSuper(&superclass, @selector(description));

You can always override inherited methods. By creating a property whose getter is the same as the signature of An inherited method, you are overriding it.

Is it bad? Yes if your implementation is not useful for debugging.

As best practice for KVC and KVO purposes it is a good idea to avoid potentially clashing with common inherited methods properties and ivars. The common approach to this is to make longer property and method names and to make them more likely to be unique. One common way is by prefixing all yours with an abbreviation common to your class or framework or code.

Using something commonly used by Apple is likely to bite you in a rare and hard to debug way. It's especially a bad idea to do this when core data is involved. Don't be reluctant to make things longer. Code completion will type for you. Plus, a nice side effect of class specific prefixing is pseudo not only the pseudo namespace but that your class specific properties, variables, constants and methods will bubble up first in code completion.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top