Objective c 使用'键进行键值编码;说明';

Objective c 使用'键进行键值编码;说明';,objective-c,properties,key-value-coding,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

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

@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*)描述)。如果现在调用description getter,当调用方希望得到类的描述时,它将返回不相关的信息


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

您可以在类中重写
description
。此方法通常仅用于调试 并且没有调用方可以期望该方法的特定输出

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

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

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

避免任何冲突。

我认为您混淆了方法和属性,并且使事情变得比实际情况更复杂

只要给定一个直接包含setter名称(即:setDate)的elementName,就可以调用选择器,并将该参数传递给object参数:

SEL selectorName = NSSelectorFromString(elementName); // elementName something like "setDate"
if ([self.newsItem respondsToSelector:selectorName])
{
    [self.newsItem performSelector: selectorName withObject: sanitisedElement];
}
至于描述方法,它已经覆盖了NSObject的描述,因此您有两个选择:以另一种方式命名它,或者保持原样,并在需要对象描述时,在Objective-C runtime的帮助下在super上调用它:

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

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

坏吗?如果您的实现对调试没有帮助,则选择“是”

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

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

这是一个非常好的观点,谢谢。我改变了我的实现,首先检查已知的、可接受的密钥列表,而不仅仅是接受发送的密钥。安全总比抱歉好。谢谢你,你的最后一点是什么被称为方法swizzling?不,那不是swizzling。如果您必须使用这样的代码,这肯定表明您的设计存在严重缺陷。谢谢,这正是我检查的原因。