Objective-C 2.0的点语法和键值编码是正交技术。您可以使用键值编码而不使用点语法,也可以使用点语法而不使用KVC。两者都使用“点语法”。在键值编码的情况下,该语法用于分隔关键路径中的元素。重要的是要记住,当您使用点语法访问属性时,会调用接收器的标准访问器方法。
然后它提供了一个例子,据说展示了两者之间的区别。但是,我仍然不明白KVC和属性访问器方法之间有什么区别?它们不是一样的吗?我如何区分调用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:
以进行评估。someObject.foo.bar.baz = theValue;
由于您没有使用字符串来标识属性,因此它是一个访问属性表达式。您在自己的代码中访问它们(发送访问器消息)。
在任何形式下,使用KVC的理由并不多;当您在编写/编译时就知道属性时,最好声明一个@property
并自己访问该属性,无论是使用属性访问表达式还是消息表达式([[[someObject foo] bar] setBaz:theValue]
)。使用KVC的时间是在运行时才知道要访问哪个属性的情况下,这种情况非常罕见。它主要是KVO、Cocoa绑定、核心动画等技术背后的构建块。
通常,您只需要自己访问属性。
[self setValue:@"mystring" forKey:@"foo"];
// read the value by key
NSString *s = [self valueForKey:@"foo"];
[myObj setFoo: @"someString"]
myObj.foo = @"someString";
- (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];
}
@property (retain) NSString *foo;
@synthesize foo;