今天在群里看到一个问题,如何在类的每个property值发生变化时去执行同一个方法?看到他这么写
- (void)setAProperty:(NSString *)aProperty {
_aProperty = aProperty;
[self xxMethod];
}
- (void)setBProperty:(NSString *)bProperty {
_bProperty = bProperty;
[self xxMethod];
}
.
.
.
就这样十来个property的setter都重写了一遍。
我想是否可以通过重写setValueForKey方法来实现,发现在给property赋值时并不执行setValueForKey方法。所以添加一个方法
- (void)xxSetValue:(id)value forKey:(NSString *)key {
[self setValue:value forKey:key];
[self xxMethod];
}
但是,只能在赋值时这样调用才有效
[xx xxSetValue:value forKey:aProperty];
无法通过直接赋值去触发。
后来想到可以通过runtime获取所有的property,然后遍历,给每个property都加kvo,在kvo监听方法里去调用[self xxMethod]。
通过runtime获取所有的property
- (NSArray *)getAllProperty {
NSMutableArray *allProperties = [NSMutableArray array];
unsigned int count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (int i = 0; i < count; i++) {
objc_property_t property = properties[i];
const char *cName = property_getName(property);
NSString *propertyName = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
[allProperties addObject:propertyName];
}
return allProperties.copy;
}
添加kvo
- (void)addKVO {
for (NSString *property in [self getAllProperties]) {
[self addObserver:self forKeyPath:property options:NSKeyValueObservingOptionNew context:nil];
}
}
kvo监听
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
[self xxMethod];
}
这样,在init的时候去调一下[self addKVO]
就行了
最后记得在dealloc的时候removeObserver
- (void)dealloc {
for (NSString *property in [self getAllProperties]) {
[self removeObserver:self forKeyPath:property];
}
}
网友评论