美文网首页iOS面试准备
iOS中kvo相关应用

iOS中kvo相关应用

作者: 楼上那只猫 | 来源:发表于2020-04-18 23:19 被阅读0次

    什么是kvo?
    一句话:kvo是一种机制,可以允许一个对象去监控另一个对象的属性变化,并且在属性变化时得到通知。

    Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects.

    如何取消系统自动发送的通知,而手动控制?
    假设Person类的firstName属性被监控,当其发生变化的时候,我们想手动控制什么时候发出通知,或者在发出通知前做其它操作,那么需要在Person中重写如下方法。

    - (void)setFirstName:(NSString *)firstName {
        // 必须手动调用
        [self willChangeValueForKey:@"firstName"];
        _firstName = firstName;
        NSLog(@"xxxx");
        // 必须手动调用
        [self didChangeValueForKey:@"firstName"];
    }
    
    + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
        if ([key isEqualToString:@"firstName"]) {
            return NO;
        }
        return YES;
    }
    

    如果被监控的属性的变化受到多个其它属性的影响,如何实现?
    如果Person中的fullName被监控,但是fullName的值受到firstName和lastName的影响。

    - (NSString *)name {
        return [NSString stringWithFormat:@"%@%@", _firstName, _lastName];
    }
    
    + (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
        NSSet * keypath = [super keyPathsForValuesAffectingValueForKey:key];
        if ([key isEqualToString:@"name"]) {
            // 指定影响name变化的属性有哪些
            NSArray * effectKeys = @[@"firstName", @"lastName"];
            keypath = [keypath setByAddingObjectsFromArray:effectKeys];
        }
        return keypath;
    }
    

    如何处理一对多的关系?
    假设,有一个Employee类,有一个属性salary。
    控制器中有一个属性emps,数组,包含的是每个Employee类的实例.
    控制器中还有一个表示总的salary的属性total。

    @interface Employee : NSObject
    @property(nonatomic, assign) NSInteger salary;
    @end
    
    @interface ViewController ()
    
    @property(nonatomic, copy) NSArray * emps;
    @property(nonatomic, strong) NSNumber * total;
    
    @end
    
        Employee * e1 = [[Employee alloc] init];
        e1.salary = 100;
        Employee * e2 = [[Employee alloc] init];
        e2.salary = 100;
        Employee * e3 = [[Employee alloc] init];
        e3.salary = 100;
        
        [self setValue:@[e1, e2, e3] forKey:@"emps"];
        
        NSIndexSet * set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.emps.count)];
        
        //这里注册为emps中的每个对象的变化都会发出通知
        [self.emps addObserver:self toObjectsAtIndexes:set forKeyPath:@"salary" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
        
        [self addObserver:self forKeyPath:@"total" options:NSKeyValueObservingOptionNew context:nil];
        
        e3.salary = 300;
    
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
        NSLog(@"change %@", change);
        if ([keyPath isEqualToString:@"salary"]) {
            [self updateTotal];
        } else {
            NSLog(@"---%ld", [self.total integerValue]);
        }
    }
    
    - (void)updateTotal {
        //每次salary变化都会重新计算总和
        NSNumber * value = [self valueForKeyPath:@"emps.@sum.salary"];
        [self setValue:value forKey:@"total"];
    }
    

    相关文章

      网友评论

        本文标题:iOS中kvo相关应用

        本文链接:https://www.haomeiwen.com/subject/vcjzvhtx.html