KVO键值依赖

120 阅读1分钟

一个属性与有限个属性关联,例如下面的totalAge与user1和user2的age息息相关,只要其中一个改变,totalAge就会改变。

//
//  Person.h
//
//  Created by Walg on 2017/7/29.
//  Copyright © 2017年 Walg. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Person : NSObject
@property (nonatomic,copy)NSString *pName;
@property (nonatomic,assign)NSInteger age;
@end

Person.m中未做任何处理!

//
//  Card.h
//
//  Created by Walg on 2017/7/29.
//  Copyright © 2017年 Walg. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
@interface Card : NSObject
@property (nonatomic,assign)NSInteger totalAge;
@property (nonatomic,strong)Person *user1;
@property (nonatomic,strong)Person *user2;
@end
//
//  Card.m
//
//  Created by Walg on 2017/7/29.
//  Copyright © 2017年 Walg. All rights reserved.
//

#import "Card.h"

@implementation Card

- (instancetype)init
{
    self = [super init];
    if (self) {
        _user1 = [[Person alloc] init];
        _user2 = [[Person alloc] init];
    }
    return self;
}

-(NSInteger)totalAge{
    return _user1.age+_user2.age;
}

+(NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key{
    NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
    NSArray *moreKeyPaths = nil;
    if ([key isEqualToString:@"totalAge"])
    {
        moreKeyPaths = [NSArray arrayWithObjects:@"user1.age", @"user2.age", nil];
    }
    
    if (moreKeyPaths)
    {
        keyPaths = [keyPaths setByAddingObjectsFromArray:moreKeyPaths];
    }
    return keyPaths;
}

@end

使用:

//
//  ViewController.m
//  键值依赖
//
//  Created by Walg on 2017/7/30.
//  Copyright © 2017年 Walg. All rights reserved.
//

#import "ViewController.h"
#import "Card.h"
@interface ViewController ()
@property (nonatomic,strong)Card *userCard;
@end

@implementation ViewController


static NSInteger NewAge(){
    static NSInteger newAge = 10;
    return newAge++;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    _userCard = [[Card alloc] init];
    _userCard.user1.pName = @"a";
    _userCard.user1.age = 18;
    
    [self.userCard addObserver:self forKeyPath:@"totalAge" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@"keyPath:%@",keyPath);
    NSLog(@"object:%@",object);
    NSLog(@"change:%@",change);
}

-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    self.userCard.user2.age = NewAge();
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}


@end

log:

2017-07-30 14:14:07.100 键值依赖[62587:1948971] keyPath:totalAge
2017-07-30 14:14:07.101 键值依赖[62587:1948971] object:<Card: 0x60800003dfa0>
2017-07-30 14:14:07.101 键值依赖[62587:1948971] change:{
    kind = 1;
    new = 28;
    old = 18;
}