有更简单的方法,以下不要再看了吧。。。
#define MZKeyPath(OBJ, PATH) \
(((void)(NO && ((void)(((typeof(OBJ))nil).PATH), NO)), @# PATH))
// 支持类或实例两种写法:
- (void)viewDidLoad
{
[super viewDidLoad];
MZKeyPath(NSString *, lowercaseString.uppercaseString.length);
MZKeyPath(self, title.lowercaseString.uppercaseString.UTF8String);
}
KVO
和 KVC
是 Objective-C
语言非常强大的两个特性,从一开始的似懂非懂到慢慢了解它的底层实现,才感受到这门动态语言的魅力所在。
KVC
允许通过一个点分隔的字符串来设置一个对象的属性值,而 KVO
可以通过点分隔的字符串来监听对象属性值的改变。
@interface Foo : NSObject
@property (nonatomic) NSString *name;
@property (nonatomic) NSInteger age;
@end
@interface Bar : NSObject
@property (nonatomic) Foo *foo;
@end
Bar *bar = [Bar new];
[bar addObserver:self
forKeyPath:@"foo.name"
options:NSKeyValueObservingOptionNew
context:NULL];
[bar setValue:@20 forKeyPath:@"foo.age"]; // 当然这个是无效的,因为 foo 为 nil
既然是字符串,人就可能犯错,因为它无法自动补全。比如常见的拼写错误,或者一个不存在的 keypath。如何能让 Xcode 在编译时就检查出这些错误呢?
受 libextobjc 的启发,本人作了一个宏来处理此事,编译时检查错误,且能自动补全。
使用方法
在 MZKVOKeyPath
宏中,第一个参数传一个 Class 类型,后面跟它的实例的属性,就像使用 .
点操作一样,可以一级一级往下。
注意:最多支持到六层 keypath,需要更多您可以自己修改。