场景一:
比如有个Student
类如下:
@interface Student : NSObject
@property (nonatomic , assign) NSInteger englishScore; // 英语分数
@property (nonatomic , assign) NSInteger mathScore; // 数学分数
@property (nonatomic , assign) NSInteger chineseScore; // 语文分数
@property (nonatomic , assign) NSInteger totalScore; // 总分
@end
一个学生的总分=英语分数+数学分数+语文分数,三门学科中任意一个分数发生变化总分都会跟着变。如果有个界面只需要展示总分,我们可以通过KVO
监听englishScore
、mathScore
、chineseScore
这三个属性的变化来实现我们的需求。那如果有10门学科,那就得监听10门学科分数的变化,这样太麻烦了,那可不可以只监听totalScore
这一关属性就达到相同的效果呢?当然是可以的,这里就需要用到联动观察
。
在Student.m
文件中首先重写totalScore
属性的getter
方法,然后重写keyPathsForValuesAffectingValueForKey
方法来设置与这个属性相关联的属性(也就是哪些属性值的改变会影响totalScore
的改变)。代码如下。
#import "Student.h"
@implementation Student
// 重写getter方法,也就是如何通过其他属性来计算totalScore的值
- (NSInteger)totalScore{
return _mathScore + _englishScore + _chineseScore;
}
// 设置关联属性(重写keyPathsForValuesAffectingValueForKey方法)
+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key{
NSMutableSet *set = [[NSMutableSet alloc] initWithSet:[super keyPathsForValuesAffectingValueForKey:key]];
if ([@"totalScore" isEqualToString:key]) {
// affectKeys是所有关联属性的属性名
NSArray *affectKeys = @[@"englishScore",@"mathScore",@"chineseScore"];
[set addObjectsFromArray:affectKeys];
}
return set;
}
@end
场景二:
Stedent
类有name
和age
两个属性,School
类有个Student
类型的属性,现在要实现Stedent
类的任意一个属性的改变都会触发KVO
,那我们可以通过KVO
同时监听Student
实例对象的2个属性变化,这和上面一样,当Stedent
类的属性有很多时就会比较麻烦,因为要同时监听很多属性的变化。其实可以和上面一样,设置好相关的keypath后,我们只需要监听School
类中的student
这一个属性就可以了。代码如下:
// Student.h
@interface Student : NSObject
@property (nonatomic , copy) NSString *name; // 姓名
@property (nonatomic , assign) NSInteger age; // 年龄
@end
// Student.m
#import "Student.h"
@implementation Student
@end
// School.h
#import "Student.h"
@interface School : NSObject
@property (nonatomic , strong) Student *student;
@end
// School.m
#import "School.h"
@implementation School
// 关键就是这里设置相关的keyPath
+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key{
NSMutableSet *set = [[NSMutableSet alloc] initWithSet:[super keyPathsForValuesAffectingValueForKey:key]];
if ([@"student" isEqualToString:key]) {
NSArray *affectKeys = @[@"_student.name",@"_student.age"];
[set addObjectsFromArray:affectKeys];
}
return set;
}
@end
网友评论