1

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

@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];
}

这很好用,但“描述”属性对我来说并不“闻起来”,因为它覆盖了基本的 NSObject 描述获取器(+(NSString *)描述)。如果现在调用描述 getter,它将在调用者期望类的描述时返回不相关的信息。

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

4

3 回答 3

2

description你可以在你的课堂上覆盖。此方法通常仅用于调试,调用者不能期望该方法的特定输出。

但是我在您的代码中看到了更普遍的问题。仅检查具有给定名称的方法是否存在。这并不意味着该方法对应于一个属性,即使那样,也不意味着该属性有一个 setter。

例如,everyNSObject响应选择器“init”,因此如果外部数据源将该键作为“elementName”发送,您的代码将立即崩溃。

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

于 2013-07-14T15:25:18.283 回答
1

我认为您将方法与属性混淆了,并且使事情变得比它们的本来面目更复杂。

给定一个直接包含 setter 名称(即setDate )的elementName就足够了,您调用选择器将该参数传递给对象参数:

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

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

struct objc_super superclass= { self.newItem, [self.newItem superclass] };
NSString* desc= objc_msgSendSuper(&superclass, @selector(description));
于 2013-07-14T15:43:46.373 回答
0

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

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

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

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

于 2013-07-14T15:44:39.763 回答