我正在使用键值编码来简化模型类的实例更新:
@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,当调用者期望描述该类时,它将返回不相关的信息。
是否可以安全地继续进行此类的键值编码(假设我被外部数据源绑定到这些属性名称)?或者更改属性名称并手动检查键/设置值是明智的吗?
答案 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常用的东西很可能会以难得的,难以调试的方式咬你。 在涉及核心数据时,这样做尤其糟糕。 不要不愿意把事情做得更久。代码完成将为您输入。另外,类特定前缀的一个很好的副作用不仅是伪命名空间伪,而且特定于类的属性,变量,常量和方法在代码完成时会先冒泡。