带有“描述”键的键值编码

时间:2013-07-14 15:00:56

标签: objective-c properties key-value-coding

我正在使用键值编码来简化模型类的实例更新:

@interface NewsItem : NSObject 
{

}

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

使用:

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

这很有效但是'description'属性对我来说没有'闻到',因为它覆盖了基本的NSObject描述getter(+(NSString *)描述)。如果现在调用了描述getter,当调用者期望描述该类时,它将返回不相关的信息。

是否可以安全地继续进行此类的键值编码(假设我被外部数据源绑定到这些属性名称)?或者更改属性名称并手动检查键/设置值是明智的吗?

3 个答案:

答案 0 :(得分:2)

您可以在班级中覆盖description。此方法通常仅用于调试 并且没有调用者可以期望该方法的特定输出。

但是我发现代码中存在更多常见问题。它只检查了一个方法 给定名称存在。这并不意味着此方法对应于属性,即使这样,也并不意味着该属性有一个setter。

例如,每个NSObject都会响应选择器“init”,所以如果是外部的话 数据源将该密钥作为“elementName”发送,您的代码将立即崩溃。

因此,需要明确的“已知密钥”列表。但是你也可以 使用外部元素名称到内部属性的映射(NSDictionary) 避免任何冲突。

答案 1 :(得分:1)

我认为你将方法与属性混淆在一起,而你正在使事情变得更加复杂。

如果 elementName 直接包含setter名称(即: setDate ),那么就足够了,调用将该参数传递给object参数的选择器:

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

至于描述方法,它已经覆盖了 NSObject 的描述,所以你有两个选择:用另一种方式命名,或者保持原样,并在上调用它在您需要对象描述时,在Objective-C运行时的帮助下

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

答案 2 :(得分:0)

您始终可以覆盖继承的方法。 通过创建一个getter与An inherited方法的签名相同的属性,您将覆盖它。

不好吗?如果您的实现对调试没有用,请单击是。

作为KVC和KVO目的的最佳实践,避免与常见的继承方法属性和ivars发生冲突是一个好主意。 常见的方法是制作更长的属性和方法名称,并使它们更有可能是唯一的。一种常见的方法是在您的所有类或框架或代码前加上常用的缩写。

使用Apple常用的东西很可能会以难得的,难以调试的方式咬你。 在涉及核心数据时,这样做尤其糟糕。 不要不愿意把事情做得更久。代码完成将为您输入。另外,类特定前缀的一个很好的副作用不仅是伪命名空间伪,而且特定于类的属性,变量,常量和方法在代码完成时会先冒泡。