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

来源:互联网 发布:跳水 违反 知乎 编辑:程序博客网 时间:2024/06/06 09:09

写作本文来由:   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:(void *)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



3 0
原创粉丝点击