iOS中的关键值编码与访问器方法

我试图理解与KVC相关的Objective C中的一些理论部分。 以下是我所做的例子。

我有类调用Cookie,它有一个像下面的属性

@property NSString *name; 

接下来,我有另一个类调用Person,它有以下属性

 @property Cookie *cookie; 

内部Person实现文件

 #import "Cookie.h" - (id)init { self = [super init]; if (self) { _cookie = [[Cookie alloc] init]; } return self; } 

在我的ViewContrtoller中,我可以编写以下两个选项来获得相同的结果。

使用KVC:

 [me valueForKeyPath:@"cookie.name"] 

使用访问器方法:

 [[me cookie] name] 

为了编写访问器方法,我不得不导入Cookie类,但在使用KVC时不需要。

除此之外,使用KVC代替或使用访问器方法有什么好处? 是否有任何性能问题或安全问题,良好的编码习惯或其他好处?

我发现KVC非常方便的一种情况是,当我不得不对某个集合对象执行某种操作时,例如find某个特定值的平均值。具体而言,我使用了KVC操作符。

例如

 [myDict valueForKey:@"gamePoints"] valueForKey:@"doubleValue"] valueForKeyPath:@"@max.self"]; 

这将帮助您从字典/对象数组中find属性“gamePoints”的最大值。

这是一个很好的文章,由马特汤普森希望这有助于你在找什么。

根据苹果文件 :

尽pipe键值编码是有效的,但它增加了一个间接的级别,比直接方法调用稍慢。 只有当您可以从其提供的灵活性中受益时,才应使用键值编码。

但我认为这可能有些过于谨慎了; 我怀疑你不需要太担心,除非你的应用程序对性能非常敏感。

在这种情况下使用KVC没有特别的好处。 一般来说,当你可以的时候,你应该更喜欢使用访问器或者点语法(比如me.cookie.name )。

KVC是用来当您想要访问的属性的名称是dynamic的。 在编译时不知道。 它来自数据(包括一个NIB,在OS X绑定的情况下)或被计算。

除了给定的答案(+1)之外,您还可以在Xcode中获得标识符完成的优势,从而降低错别字的可能性。 如果你在语义上使用它,导入这个类是一个很好的策略。 把它看作是“我使用的东西”,这可以帮助你理解你的代码。

使用KVO的好地方是unit testing。 当你有以下的类接口:

 @interface ServerCommunicationManager : NSObject { NSMutableArray *commandQueue; BOOL chanelFree; } - (void)send:(NSDictionary *)dictionary; @end 

然后发送执行:

 - (void)send:(NSDictionary *)json { if ( YES == chanelFree ) { // send command immediately } else { [commandQueue addObject:json]; } } 

如果我们想testing发送实现而不暴露commandQueue(因此没有制动封装),我们可以使用KVO:

 -(void)testSend { ServerCommunicationManager* aTestObj = [ServerCommunicationManager new]; //prepare conditions [aTestObj setValue:@NO forKey:@"channelFree"]; NSDictionary* dummyReq = @{}; [aTestObj send:dummyReq]; //check commandQueue state XCTAssertEqualObjects(dummyReq, [[aTestObj valueForKey:@"commandQueue"] firstObject]); XCTAssertTrue(1 == [[aTestObj valueForKey:@"commandQueue"] count]); //more tests } 

KVC允许你做KVO:也就是说,如果你正在观察一个variables,当且仅当这个变化发生在KVC上的时候,你才会被通知它的变化。 如果你直接使用setter修改一个variables,你将不会被通知它的变化