【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)
* 第三步 移除观察者
*/
- 数组不能放在UIViewController里面,在这里面的数组是监听不到数组大小的变化的,需要将需要监听的数组封装到model里面<
 
model类为: 将监听的数组封装到model里,不能监听UIViewController里面的数组
两个属性 一个 字符串类的姓名,一个数组类的modelArray,我们需要的就是监听modelArray里面元素的变化
- @interface model : NSObject
 - @property(nonatomic, copy)NSString *name;
 - @property(nonatomic, retain)NSMutableArray *modelArray;
 
1 建立观察者及观察的对象
第一步 建立观察者及观察的对象
[_modeladdObserver:selfforKeyPath:@"modelArray"options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOldcontext:NULL];
第二步 处理key的变化(根据key的变化刷新UI)
最重要的就是添加数据这里
- 不能这样 [_model.modelArray addObject]方法,需要这样调用 [[_model mutableArrayValueForKey:@"modelArray"] addObject:str];原因稍后说明。
 
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
- {
 - if ([keyPath isEqualToString:@"modelArray"]) {
 - [_tableView reloadData];
 - }
 - }
 
第三步 移除观察者
- if (_model != nil) {
 - [_model removeObserver:self forKeyPath:@"modelArray"];
 - }
 
以下附上本文代码:
代码中涉及三点
1 根据数组动态刷新tableview;
2 定时器的使用(涉及循环引用问题);
3 使用KVC优化model的初始化代码。
没找到上传整个工程的方法,暂时附上代码
1 NSTimer相关
- //
 - // NSTimer+DelegateSelf.h
 - // KVOTableview
 - //
 - // Created by 程立彬 on 14-8-8.
 - // Copyright (c) 2014年 chenglb. All rights reserved.
 - //
 - //为防止controller和nstimer之间的循环引用,delegate指向当前单例,而不指向controller
 - #import <Foundation/Foundation.h>
 - @interface NSTimer (DelegateSelf)
 - +(NSTimer *)scheduledTimerWithTimeInterval:(int)timeInterval block:(void(^)())block repeats:(BOOL)yesOrNo;
 - @end
 
- //
 - // NSTimer+DelegateSelf.m
 - // KVOTableview
 - //
 - // Created by 程立彬 on 14-8-8.
 - // Copyright (c) 2014年 chenglb. All rights reserved.
 - //
 - #import "NSTimer+DelegateSelf.h"
 - @implementation NSTimer (DelegateSelf)
 - +(NSTimer *)scheduledTimerWithTimeInterval:(int)timeInterval block:(void(^)())block repeats:(BOOL)yesOrNo
 - {
 - return [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(callBlock:) userInfo:[block copy] repeats:yesOrNo];
 - }
 - +(void)callBlock:(NSTimer *)timer
 - {
 - void(^block)() = timer.userInfo;
 - if (block != nil) {
 - block();
 - }
 - }
 - @end
 
2 model相关
- //
 - // model.h
 - // KVOTableview
 - //
 - // Created by 程立彬 on 14-8-8.
 - // Copyright (c) 2014年 chenglb. All rights reserved.
 - //
 - #import <Foundation/Foundation.h>
 - @interface model : NSObject
 - @property(nonatomic, copy)NSString *name;
 - @property(nonatomic, retain)NSMutableArray *modelArray;
 - -(id)initWithDic:(NSDictionary *)dic;
 - @end
 
- //
 - // model.m
 - // KVOTableview
 - //
 - // Created by 程立彬 on 14-8-8.
 - // Copyright (c) 2014年 chenglb. All rights reserved.
 - //
 - //KVC的应用 简化冗余代码
 - #import "model.h"
 - @implementation model
 - -(id)initWithDic:(NSDictionary *)dic
 - {
 - self = [super init];
 - if (self) {
 - [self setValuesForKeysWithDictionary:dic];
 - }
 - return self;
 - }
 - -(void)setValue:(id)value forUndefinedKey:(NSString *)key
 - {
 - NSLog(@"undefine key ---%@",key);
 - }
 - @end
 
3 UIViewController相关
- //
 - // RootViewController.m
 - // KVOTableview
 - //
 - // Created by 程立彬 on 14-8-8.
 - // Copyright (c) 2014年 chenglb. All rights reserved.
 - //
 - /*
 - * 第一步 建立观察者及观察的对象
 - * 第二步 处理key的变化(根据key的变化刷新UI)
 - * 第三步 移除观察者
 - */
 - #import "RootViewController.h"
 - #import "NSTimer+DelegateSelf.h"
 - #import "model.h"
 - #define TimeInterval 3.0
 - @interface RootViewController ()<UITableViewDelegate,UITableViewDataSource>
 - @property(nonatomic, retain)NSTimer *timer;
 - @property(nonatomic, retain)UITableView *tableView;
 - @property(nonatomic, retain)model *model;
 - @end
 - @implementation RootViewController
 - - (void)dealloc
 - {
 - //第三步
 - if (_model != nil) {
 - [_model removeObserver:self forKeyPath:@"modelArray"];
 - }
 - //停止定时器
 - if (_timer != nil) {
 - [_timer invalidate];
 - _timer = nil;
 - }
 - }
 - - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
 - {
 - self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
 - if (self) {
 - NSDictionary *dic = [NSDictionary dictionaryWithObject:[NSMutableArray arrayWithCapacity:0] forKey:@"modelArray"];
 - self.model = [[model alloc] initWithDic:dic];
 - }
 - return self;
 - }
 - - (void)viewDidLoad
 - {
 - [super viewDidLoad];
 - //第一步
 - [_model addObserver:self forKeyPath:@"modelArray" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
 - self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
 - _tableView.delegate = self;
 - _tableView.dataSource = self;
 - _tableView.backgroundColor = [UIColor lightGrayColor];
 - [self.view addSubview:_tableView];
 - //定时添加数据
 - [self startTimer];
 - }
 - //添加定时器
 - -(void)startTimer
 - {
 - __block RootViewController *bself = self;
 - _timer = [NSTimer scheduledTimerWithTimeInterval:TimeInterval block:^{
 - [bself changeArray];
 - } repeats:YES];
 - }
 - //增加数组中的元素 自动刷新tableview
 - -(void)changeArray
 - {
 - NSString *str = [NSString stringWithFormat:@"%d",arc4random()%100];
 - [[_model mutableArrayValueForKey:@"modelArray"] addObject:str];
 - }
 - //第二步 处理变化
 - -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(voidvoid *)context
 - {
 - if ([keyPath isEqualToString:@"modelArray"]) {
 - [_tableView reloadData];
 - }
 - }
 - -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 - {
 - return [_model.modelArray count];
 - }
 - - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
 - {
 - static NSString *cellidentifier = @"cellIdentifier";
 - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellidentifier];
 - if (cell == nil) {
 - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier];
 - }
 - cell.textLabel.text = _model.modelArray[indexPath.row];
 - return cell;
 - }
 - - (void)didReceiveMemoryWarning
 - {
 - [super didReceiveMemoryWarning];
 - // Dispose of any resources that can be recreated.
 - }
 - @end
 
                    
                
                
            
        
浙公网安备 33010602011771号