KVC和Properties之间有什么区别?
所以,我已经注意到这KVC和Properties之间有什么区别?
的Objective-C 2.0的点语法和键值编码正交技术文档上阅读了。无论您是否使用点语法,都可以使用键值编码,无论您是否使用KVC,都可以使用点语法。两者都使用“点语法”。在键值编码的情况下,语法用于在键路径中分隔元素。请记住,使用点语法访问属性时,需要调用接收方的标准存取方法。
然后,它提供了一个例子,据说显示两者之间的差异。但是,我仍然不明白,KVC和property accessor方法有什么区别?他们不一样吗?如何区分调用setValue:forKeyPath的点和简单访问器?
不过,我还是不明白,什么是KVC和属性访问方法之间的区别?
KVC是调用属性访问器方法或以其他方式访问属性的一种方法。
“否则访问”是什么意思?对于KVC而言,没有访问器方法的实例变量会被视为非正式属性。如果没有找到匹配的访问器对,它将直接获取或设置实例变量的值。 (是的,这在现代代码中是不值得使用的,对于任何你想要访问的任何东西,总是声明一个@property
,反过来也不要使用KVC来访问任何非公有财产。)
属性访问器方法是KVC在存在的情况下会调用的方法(KVC和每个理智的程序员都优先考虑直接ivar访问)。访问者可以获取或设置实例变量,如合成访问者所做的那样,或者访问某些其他存储。
访问器是实现,属性是接口,KVC是使用它们的一种方式。
我该如何区分调用setValue的点:forKeyPath:和简单访问器?
关键路径是一个字符串,而属性访问表达式是一个表达式。编译器评估属性访问表达式并将其转换为一个或多个Objective-C消息,而关键路径由KVC在运行时评估。
所以,当你使用一个关键路径:
[someObject setValue:theValue forKeyPath:@"foo.bar.baz"];
你知道这是一个关键的路径,因为(1)它是一个字符串,在这种情况下,由字符串文本语法@"…"
表示,和(2 )您将密钥路径字符串传递给setValue:forKeyPath:
以供其评估。
使用关键路径使用KVC访问指定的属性。它会代表您发送任何相关的访问者消息。
当您使用属性的访问表达:
someObject.foo.bar.baz = theValue;
你知道这是一个属性访问表达式,因为你不是识别与字符串的属性。您正在使用自己的代码访问它们(发送访问者消息)。
没有什么理由以任何形式使用KVC;当您在作者/编译时知道该属性时,最好声明一个@property
并自行访问该属性,无论是使用属性访问表达式还是消息表达式([[[someObject foo] bar] setBaz:theValue]
)。使用KVC的时间是在运行时间之前不知道要访问的属性,这很少见。它主要是KVO,Cocoa Bindings,Core Animation等部分背后的构建块技术。
大多数情况下,您只需要自己访问属性。
键值编码允许您使用属性的字符串名称通过代码设置和获取属性的值。例如,如果我有一个名为foo的属性,其类型为NSString:
[self setValue:@"mystring" forKey:@"foo"];
// read the value by key
NSString *s = [self valueForKey:@"foo"];
点语法是编译语法糖。作为一个个人喜好(如一些不同意 - 罚款)我不使用点语法,但我仍然可以使用KVC:
[myObj setFoo: @"someString"]
等于:
myObj.foo = @"someString";
他们是正交的,不同的概念,但两者都涉及您如何与属性进行交互
最后,您提到属性语法。又一个正交的概念,但涉及到处理财产。
使用objective-c,约定很重要。跟着他们。属性是属性为GET的名称并设置[名称]的任务:
- (NSString*)foo
{
return _foo; // defined as (NSString*)_foo in header
}
- (void) setFoo: (NSString*)foo
{
if (foo == _foo)
return;
NSString* curr = _foo;
_foo = [foo retain];
[curr release];
}
现在,谁愿意写这样的事情每次。在.M
@property (retain) NSString *foo;
然后:那么,进入@property语法:
在头
@synthesize foo;
这就是手写属性访问的等价物。它是编译器语法糖,它根据属性的属性来扩展属性代码。
文档:
**“使用KVC的时间是当你不知道你想访问什么属性,直到运行时间”**从你的答案是我正在寻找,谢谢。 – km3h
这对我真的很有帮助。我在脑海里认为**使用KVC的时间是在运行时间之前不知道你想访问什么属性,**这可能是原因,但我不确定。你让我相信我的想法。 –
彼得你陈述“,反过来说,不要使用KVC来访问任何非公共财产。“我发现如果一个属性声明为只读,然后在实现中重新声明为读写,那么KVC将无耻地写入该属性。是否没有办法阻止它?我试过(BOOL)accessInstanceVariablesDirectly {返回NO;}但这并不妨碍KVC写入属性 –