似乎-valueForKey:
和-valueForKeyPath:
使用任意方法,不仅适用于属性。这看起来很方便:
I first stumbled upon it in Interface Builder,然后做了一些实验:
// Thing.h
#import <Foundation/Foundation.h>
@interface Thing : NSObject
- (BOOL) alwaysYES;
- (BOOL) alwaysNO;
@end
// Thing.m
#import "Thing.h"
@implementation Thing
- (BOOL) alwaysYES
{
return YES;
}
- (BOOL) alwaysNO
{
return NO;
}
@end
我可以通过-valueForKey:
和-valueForKeyPath:
调用这些方法,尽管它们是普通方法而且没有属性:
Thing *aThing = [[Thing alloc] init];
id result;
result = [aThing valueForKey:@"alwaysYES"];
NSLog(@"result is: %@", result);
result = [aThing valueForKeyPath:@"alwaysNO"];
NSLog(@"result is: %@", result);
编译,运行并给出正确的结果。这记录在哪里?我可以安全地使用它吗?我怎么能理解呢?
答案 0 :(得分:3)
Cocoa的键值编码(KVC)系统比Objective-C中对显式属性(用@property
声明)的支持更旧,因此KVC是根据方法定义的,而不是属性。
“Default Search Pattern for valueForKey:
” in the Key-Value Coding Programming Guide阐明了valueForKey:
如何决定做什么。它首先查找(除其他外)一个方法,其名称正是您传递给valueForKey:
的密钥。以下是文档中引用的完整搜索模式:
在接收者的类中搜索名称与模式
get<Key>
,<key>
或is<Key>
匹配的访问者方法。如果找到这样的方法,则调用它。如果方法的结果类型是对象指针类型,则只返回结果。如果结果的类型是NSNumber
转换支持的标量类型之一,则返回NSNumber
。否则,转换完成并返回NSValue
。任意类型的结果将转换为NSValue
个对象,而不仅仅是NSPoint
,NSRange
,NSRect
和NSSize
类型。否则(没有找到简单的访问器方法),在接收器的类中搜索名称与模式
countOf<Key>
和objectIn<Key>AtIndex:
匹配的方法(对应于{定义的基本方法) {1}}类)和NSArray
(对应<key>AtIndexes:
方法NSArray
)。 如果找到objectsAtIndexes:
方法和其他两种可能方法中的至少一种,则返回响应所有countOf<Key>
方法的集合代理对象。发送到集合代理对象的每条NSArray
消息都会导致NSArray
,countOf<Key>
和objectIn<Key>AtIndex:
消息的某种组合被发送到<key>AtIndexes:
的原始接收方。如果接收者的类还实现了一个名称与模式valueForKey:
匹配的可选方法,那么该方法将在适当时使用,以获得最佳性能。否则(没有找到简单的访问器方法或数组访问方法集),在接收器的类中搜索名称与模式
get<Key>:range:
,countOf<Key>
匹配的三种方法,和enumeratorOf<Key>
(对应于memberOf<Key>:
类定义的基本方法)。 如果找到所有三个方法,则返回响应所有NSSet
方法的集合代理对象。发送到集合代理对象的每条NSSet
消息都会导致NSSet
,countOf<Key>
和enumeratorOf<Key>
消息的某种组合被发送到memberOf<Key>:
的原始接收方否则(没有找到简单的访问器方法或集合访问方法),如果接收者的类方法
valueForKey:
返回accessInstanceVariablesDirectly
,则在接收者的类中搜索实例变量其名称与模式YES
,_<key>
,_is<Key>
或<key>
按此顺序匹配。如果找到这样的实例变量,则返回接收器中的实例变量的值。如果结果的类型是is<Key>
转换支持的标量类型之一,则返回NSNumber
。否则,转换完成并返回NSNumber
。任意类型的结果将转换为NSValue
个对象,而不仅仅是NSValue
,NSPoint
,NSRange
和NSRect
类型。- 醇>
如果上述情况均未发生,则返回默认实现调用
NSSize
的结果。
答案 1 :(得分:1)
这与您可以使用属性语法调用这些方法的事实并行:
BOOL ok = aThing.alwaysYES
在这种情况下,在您的情况下,完全相同的事情发生:the first thing the runtime tries将此视为getter方法。你写的是一个getter方法。
至于你的问题&#34;我可以安全地使用它吗?安全地是,但你正在做的事情有点愚蠢,因为你知道(并且声明)这些方法存在。 KVC正在探索是否存在方法。如果您有理由通过字符串名称指定其中一种方法,则有比使用KVC更好的方法来调用它。
答案 2 :(得分:0)
属性在运行时没什么特别之处;他们生成一个符合KVC的getter和setter(如果不是readonly
);例如:
@property NSString *aString;
将生成:
- (NSString)aString {
...
}
- (void)setAString(NSString *string) {
...
}
就像你在标题中声明了这些方法一样(它本身是可选的)。