【iOS】KVO方式监听数组的变化动态刷新tableView

原文地址 http://blog.csdn.net/chenglibin1988/article/details/38442307

 

!!!!!!model中的数组添加数据时需要注意

不能这样 [_model.modelArray addObject]方法,需要这样调用   [[_model mutableArrayValueForKey:@"modelArray"] addObject:str];

!!!!!!

 

 

写作本文来由:   iOS默认不支持对数组的KVO,因为普通方式监听的对象的地址的变化,而数组地址不变,而是里面的值发生了改变

整个过程需要三个步骤 (与普通监听一致)

 

/*

    *  第一步 建立观察者及观察的对象

    *  第二步 处理key的变化(根据key的变化刷新UI)

    *  第三步 移除观察者

*/

 

[objc] view plaincopy
 
  1. 数组不能放在UIViewController里面,在这里面的数组是监听不到数组大小的变化的,需要将需要监听的数组封装到model里面<  

 

 

model类为: 将监听的数组封装到model里,不能监听UIViewController里面的数组

两个属性 一个 字符串类的姓名,一个数组类的modelArray,我们需要的就是监听modelArray里面元素的变化

 

[objc] view plaincopy
 
  1. @interface model : NSObject  
  2. @property(nonatomic, copy)NSString *name;  
  3. @property(nonatomic, retain)NSMutableArray *modelArray;  

 

 

1 建立观察者及观察的对象

   第一步  建立观察者及观察的对象

    [_modeladdObserver:selfforKeyPath:@"modelArray"options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOldcontext:NULL];

   第二步 处理key的变化(根据key的变化刷新UI)

    最重要的就是添加数据这里

 

[objc] view plaincopy
 
  1. 不能这样 [_model.modelArray addObject]方法,需要这样调用   [[_model mutableArrayValueForKey:@"modelArray"] addObject:str];原因稍后说明。  

 

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

 

[objc] view plaincopy
 
  1. {  
  2.     if ([keyPath isEqualToString:@"modelArray"]) {  
  3.         [_tableView reloadData];  
  4.     }  
  5. }  

 

 

    第三步 移除观察者

 

[objc] view plaincopy
 
  1. if (_model != nil) {  
  2.     [_model removeObserver:self forKeyPath:@"modelArray"];  
  3. }  


以下附上本文代码:

 

代码中涉及三点

1 根据数组动态刷新tableview;

2 定时器的使用(涉及循环引用问题);

3 使用KVC优化model的初始化代码。

没找到上传整个工程的方法,暂时附上代码

1  NSTimer相关

 

[objc] view plaincopy
 
  1. //  
  2. //  NSTimer+DelegateSelf.h  
  3. //  KVOTableview  
  4. //  
  5. //  Created by 程立彬 on 14-8-8.  
  6. //  Copyright (c) 2014年 chenglb. All rights reserved.  
  7. //  
  8.   
  9. //为防止controller和nstimer之间的循环引用,delegate指向当前单例,而不指向controller  
  10.   
  11. #import <Foundation/Foundation.h>  
  12.   
  13. @interface NSTimer (DelegateSelf)  
  14.   
  15. +(NSTimer *)scheduledTimerWithTimeInterval:(int)timeInterval block:(void(^)())block repeats:(BOOL)yesOrNo;  
  16.   
  17. @end  


[objc] view plaincopy
 
  1. //  
  2. //  NSTimer+DelegateSelf.m  
  3. //  KVOTableview  
  4. //  
  5. //  Created by 程立彬 on 14-8-8.  
  6. //  Copyright (c) 2014年 chenglb. All rights reserved.  
  7. //  
  8.   
  9. #import "NSTimer+DelegateSelf.h"  
  10.   
  11. @implementation NSTimer (DelegateSelf)  
  12.   
  13. +(NSTimer *)scheduledTimerWithTimeInterval:(int)timeInterval block:(void(^)())block repeats:(BOOL)yesOrNo  
  14. {  
  15.     return [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(callBlock:) userInfo:[block copy] repeats:yesOrNo];  
  16. }  
  17.   
  18.   
  19. +(void)callBlock:(NSTimer *)timer  
  20. {  
  21.     void(^block)() = timer.userInfo;  
  22.     if (block != nil) {  
  23.         block();  
  24.     }  
  25. }  
  26.   
  27. @end  


2 model相关

 

 

[objc] view plaincopy
 
  1. //  
  2. //  model.h  
  3. //  KVOTableview  
  4. //  
  5. //  Created by 程立彬 on 14-8-8.  
  6. //  Copyright (c) 2014年 chenglb. All rights reserved.  
  7. //  
  8.   
  9. #import <Foundation/Foundation.h>  
  10.   
  11. @interface model : NSObject  
  12. @property(nonatomic, copy)NSString *name;  
  13. @property(nonatomic, retain)NSMutableArray *modelArray;  
  14.   
  15. -(id)initWithDic:(NSDictionary *)dic;  
  16.   
  17. @end  


[objc] view plaincopy
 
  1. //  
  2. //  model.m  
  3. //  KVOTableview  
  4. //  
  5. //  Created by 程立彬 on 14-8-8.  
  6. //  Copyright (c) 2014年 chenglb. All rights reserved.  
  7. //  
  8.   
  9.   
  10. //KVC的应用  简化冗余代码  
  11. #import "model.h"  
  12.   
  13. @implementation model  
  14.   
  15. -(id)initWithDic:(NSDictionary *)dic  
  16. {  
  17.     self = [super init];  
  18.     if (self) {  
  19.         [self setValuesForKeysWithDictionary:dic];  
  20.     }  
  21.       
  22.     return self;  
  23. }  
  24.   
  25. -(void)setValue:(id)value forUndefinedKey:(NSString *)key  
  26. {  
  27.     NSLog(@"undefine key ---%@",key);  
  28. }  
  29.   
  30. @end  


3 UIViewController相关

 

 

[objc] view plaincopy
 
    1. //  
    2. //  RootViewController.m  
    3. //  KVOTableview  
    4. //  
    5. //  Created by 程立彬 on 14-8-8.  
    6. //  Copyright (c) 2014年 chenglb. All rights reserved.  
    7. //  
    8.   
    9. /* 
    10.     *  第一步 建立观察者及观察的对象 
    11.     *  第二步 处理key的变化(根据key的变化刷新UI) 
    12.     *  第三步 移除观察者 
    13.   
    14. */  
    15.   
    16. #import "RootViewController.h"  
    17. #import "NSTimer+DelegateSelf.h"  
    18. #import "model.h"  
    19.   
    20. #define TimeInterval 3.0  
    21.   
    22. @interface RootViewController ()<UITableViewDelegate,UITableViewDataSource>  
    23.   
    24. @property(nonatomic, retain)NSTimer *timer;  
    25. @property(nonatomic, retain)UITableView    *tableView;  
    26. @property(nonatomic, retain)model *model;  
    27.   
    28. @end  
    29.   
    30. @implementation RootViewController  
    31.   
    32. - (void)dealloc  
    33. {  
    34.     //第三步  
    35.     if (_model != nil) {  
    36.         [_model removeObserver:self forKeyPath:@"modelArray"];  
    37.     }  
    38.     //停止定时器  
    39.     if (_timer != nil) {  
    40.         [_timer invalidate];  
    41.         _timer = nil;  
    42.     }  
    43. }  
    44.   
    45. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
    46. {  
    47.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
    48.     if (self) {  
    49.   
    50.         NSDictionary *dic = [NSDictionary dictionaryWithObject:[NSMutableArray arrayWithCapacity:0] forKey:@"modelArray"];  
    51.           
    52.         self.model = [[model alloc] initWithDic:dic];  
    53.       
    54.     }  
    55.     return self;  
    56. }  
    57.   
    58. - (void)viewDidLoad  
    59. {  
    60.     [super viewDidLoad];  
    61.       
    62.     //第一步  
    63.     [_model addObserver:self forKeyPath:@"modelArray" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];  
    64.       
    65.     self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];  
    66.     _tableView.delegate        = self;  
    67.     _tableView.dataSource      = self;  
    68.     _tableView.backgroundColor = [UIColor lightGrayColor];  
    69.     [self.view addSubview:_tableView];  
    70.       
    71.     //定时添加数据  
    72.     [self startTimer];  
    73.       
    74. }  
    75.   
    76. //添加定时器  
    77. -(void)startTimer  
    78. {  
    79.     __block RootViewController *bself = self;  
    80.       
    81.     _timer = [NSTimer scheduledTimerWithTimeInterval:TimeInterval block:^{  
    82.           
    83.         [bself changeArray];  
    84.     } repeats:YES];  
    85.   
    86. }  
    87.   
    88. //增加数组中的元素 自动刷新tableview  
    89. -(void)changeArray  
    90. {  
    91.       
    92.     NSString *str = [NSString stringWithFormat:@"%d",arc4random()%100];  
    93.     [[_model mutableArrayValueForKey:@"modelArray"] addObject:str];  
    94.       
    95. }  
    96.   
    97.   
    98. //第二步 处理变化  
    99. -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(voidvoid *)context  
    100. {  
    101.     if ([keyPath isEqualToString:@"modelArray"]) {  
    102.         [_tableView reloadData];  
    103.     }  
    104. }  
    105.   
    106.   
    107.   
    108.   
    109. -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  
    110. {  
    111.     return  [_model.modelArray count];  
    112. }  
    113.   
    114. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;  
    115. {  
    116.     static NSString *cellidentifier = @"cellIdentifier";  
    117.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellidentifier];  
    118.     if (cell == nil) {  
    119.         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier];  
    120.     }  
    121.       
    122.     cell.textLabel.text = _model.modelArray[indexPath.row];  
    123.     return cell;  
    124. }  
    125.   
    126.   
    127. - (void)didReceiveMemoryWarning  
    128. {  
    129.     [super didReceiveMemoryWarning];  
    130.     // Dispose of any resources that can be recreated.  
    131. }  
    132.   
    133. @end  
posted @ 2015-10-22 15:16  lxl奋小斗  阅读(1121)  评论(0编辑  收藏  举报