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

iOS中的键值编码与访问器方法,ios,objective-c,kvc,Ios,Objective C,Kvc,我试图理解目标C中与KVC相关的一些理论部分。下面是我做的例子 我有一个类调用Cookie,它有如下属性 @property NSString *name; 接下来,我有另一个类callperson,它有以下属性 @property Cookie *cookie; 内部人员实现文件 #import "Cookie.h" - (id)init { self = [super init]; if (self) { _cookie = [[Cookie alloc

我试图理解目标C中与KVC相关的一些理论部分。下面是我做的例子

我有一个类调用Cookie,它有如下属性

@property NSString *name;
接下来,我有另一个类callperson,它有以下属性

@property Cookie *cookie;
内部人员实现文件

#import "Cookie.h"

- (id)init
{
    self = [super init];
    if (self) {
        _cookie = [[Cookie alloc] init];
    }
    return self;
}
在我的ViewController中,我可以编写以下两个选项以获得相同的结果

使用KVC:

[me valueForKeyPath:@"cookie.name"]
使用访问器方法:

[[me cookie] name]
要编写访问器方法,我必须导入Cookie类,但在使用KVC时不需要


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

我发现KVC非常方便的一种情况是,我必须对收集对象执行某种操作,例如查找特定值的平均值。具体而言,我使用了KVC运算符

比如说

[myDict valueForKey:@"gamePoints"] valueForKey:@"doubleValue"] valueForKeyPath:@"@max.self"];
这将帮助您从一系列字典/对象中找到属性“gamePoints”的最大值


希望这有助于实现您的目标。

在这种情况下,使用KVC没有特别的好处。通常,如果可以,您应该更喜欢使用访问器或点语法(例如,
me.cookie.name

KVC用于您要访问的属性的名称为动态时。它在编译时是未知的。它来自数据(包括NIB,在OS X上绑定的情况下)或是计算出来的。

除了给定的答案(+1)之外,您还可以在Xcode中获得标识符完成的优势,这降低了输入错误的概率。如果您在语义上使用该类,那么导入该类是一个很好的策略。将其视为“我使用的物品清单”,这有助于理解您的代码。

根据:

尽管键值编码是有效的,但它增加了一个间接级别,比直接方法调用稍微慢一点。只有在能够从键值编码提供的灵活性中获益时,才应该使用键值编码


但我认为这可能有点过于谨慎;除非您的应用程序对性能非常敏感,否则我怀疑您是否需要太多担心。

使用KVO的好地方是单元测试。当您具有以下类接口时:

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

}
如果我们想在不公开commandQueue的情况下测试send实现(因此没有阻止封装),我们可以使用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:也就是说,如果您正在观察一个变量,只有当且仅当使用KVC进行更改时,才会通知您该变量的更改。如果直接使用变量的setter修改变量,则不会通知您其更改