KVO—联动观察

2019-12-18  本文已影响0人  一叶知秋0830

场景一:

比如有个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监听englishScoremathScorechineseScore这三个属性的变化来实现我们的需求。那如果有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类有nameage两个属性,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
上一篇 下一篇

猜你喜欢

热点阅读