我试图理解目标C中与KVC相关的一些理论部分。以下是我已经完成的例子。
我有课程调用Cookie,它有一个如下所示的属性
@property NSString *name;
接下来,我有另一个类调用Person,它有以下属性
@property Cookie *cookie;
Inside 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或使用访问器方法有什么好处?是否有任何性能问题或安全问题或良好的编码实践或任何其他好处?
答案 0 :(得分:2)
我发现KVC非常方便的一种情况是我必须对集合对象执行某种操作,例如查找特定值的平均值。特别是我使用了KVC操作符。
例如
[myDict valueForKey:@"gamePoints"] valueForKey:@"doubleValue"] valueForKeyPath:@"@max.self"];
这将帮助您找到该物业的最大价值' gamePoints'来自一系列词典/对象。
Here is an excellent article by Mattt Thompson 希望这有助于你所寻找的东西。
答案 1 :(得分:2)
根据Apple Docs:
虽然键值编码是有效的,但它增加的间接级别比直接方法调用稍慢。只有在您可以从其提供的灵活性中受益时,才应使用键值编码。
但我认为这可能有点过于谨慎;我怀疑你需要太多担心,除非你的应用程序对性能非常敏感。
答案 2 :(得分:1)
在这种情况下,使用KVC没有特别的好处。通常,您应该尽可能使用访问者或点语法(例如me.cookie.name
)。
KVC适用于您要访问的媒体资源的名称是动态的。它在编译时不知道。它来自数据(包括NIB,在OS X上绑定的情况下)或计算。
答案 3 :(得分:0)
除了给定的答案(+1)之外,您还可以在Xcode中获得标识符完成的优势,从而降低拼写错误的可能性。如果您在语义上使用它,导入类是一个很好的策略。将其视为“我使用的物品清单”,这有助于理解您的代码。
答案 4 :(得分:0)
使用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的情况下测试发送实现(因此没有制动封装),我们可以使用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
}
答案 5 :(得分:-1)
KVC允许您进行KVO:也就是说,如果您正在观察变量,当且仅当使用KVC进行更改时,才会通知您的更改。如果直接使用其setter修改变量,则不会收到有关其更改的通知