使用KVO監聽數組的變化


以前有個需求,需要監聽數組長度的變化。使用KVO直接監聽數組本身,由於數組地址並沒有發生改變,所以並不能監聽到。試了好多方法,都沒有能夠實現。知道最近聽的一場公開課中,才掌握了正確的監聽方法

先舉個錯誤的例子

@interface ViewController ()
@property (nonatomic, strong) NSMutableArray *array;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self.array addObserver:self forKeyPath:@"count" options:(NSKeyValueObservingOptionNew) context:nil];
}

 

這樣會直接報錯,NSMutableArray 沒有 count的 keyPath。

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[<__NSArrayM 0x282195770> addObserver:forKeyPath:options:context:] is not supported. Key path: count'

 

正確的打開方式是這樣的,不多說廢話,直接上代碼

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic, strong) NSMutableArray *array;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
 
    [self addObserver:self forKeyPath:NSStringFromSelector(@selector(array)) options:(NSKeyValueObservingOptionNew) context:nil];
}



- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context {
    
    /*
     typedef NS_ENUM(NSUInteger, NSKeyValueChange) {
     NSKeyValueChangeSetting = 1,
     NSKeyValueChangeInsertion = 2,
     NSKeyValueChangeRemoval = 3,
     NSKeyValueChangeReplacement = 4,
     };
     */

    
    //第一次觸發是添加一條數據,kind為2,對應的是NSKeyValueChangeInsertion
    /*
     {
    indexes = "<_NSCachedIndexSet: 0x280495620>[number of indexes: 1 (in 1 ranges), indexes: (0)]";
    kind = 2;
    new =     (
               "NewData- 1"
               );
     }
     */
    
    
    //第二次觸發是修改一條數據,kind為4,對應的是NSKeyValueChangeReplacement
    /*
     {
     indexes = "<_NSCachedIndexSet: 0x280495620>[number of indexes: 1 (in 1 ranges), indexes: (0)]";
     kind = 4;
     new =     (
     "NewData- 2"
     );
     }
     */
    
    //第三次次觸發是刪除一條數據,kind為3,對應的是NSKeyValueChangeRemoval
    /*
     {
     indexes = "<_NSCachedIndexSet: 0x280495620>[number of indexes: 1 (in 1 ranges), indexes: (0)]";
     kind = 3;
     }
     */
    
    
    NSLog(@"我觸發了");
}




- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    static NSInteger a = 0;
    a++;
    
    //這一步特別重要
    NSMutableArray *tempArray = [self mutableArrayValueForKey:NSStringFromSelector(@selector(array))];
    if (1 == a) {//插入一條
        [tempArray addObject:[NSString stringWithFormat:@"NewData- %tu",a]];
    } else if (2 == a) {//修改一條
        tempArray[0] = [NSString stringWithFormat:@"NewData- %tu",a];
    } else if (3 == a) {
        [tempArray removeAllObjects];
    }
}


- (NSMutableArray *)array {
    if (!_array) {
        _array = [NSMutableArray array];
    }
    return _array;
}

- (void)dealloc {
    [self removeObserver:self forKeyPath:NSStringFromSelector(@selector(array))];
}

 KVO三部曲,注冊監聽,實現代理方法,移除監聽。

在監聽數組變化時,需要特別注意,

    NSMutableArray *tempArray = [self mutableArrayValueForKey:NSStringFromSelector(@selector(array))];

 一定要使用該方法復制出一個數組,而不是使用數組本身進行操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM