天天看點

KVO方式監聽數組的變化動态重新整理tableView

寫作本文來由:   iOS預設不支援對數組的KVO,因為普通方式監聽的對象的位址的變化,而數組位址不變,而是裡面的值發生了改變

整個過程需要三個步驟 (與普通監聽一緻)

/*

    *  第一步 建立觀察者及觀察的對象

    *  第二步 處理key的變化(根據key的變化重新整理UI)

    *  第三步 移除觀察者

*/

[objc] view plaincopy

    數組不能放在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  

    #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();  

2 model相關

    //  model.h  

    -(id)initWithDic:(NSDictionary *)dic;  

    //  model.m  

    //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);  

3 UIViewController相關

    //  RootViewController.m  

    /*

        *  第一步 建立觀察者及觀察的對象

        *  第二步 處理key的變化(根據key的變化重新整理UI)

        *  第三步 移除觀察者

    */  

    #import "RootViewController.h"  

    #define TimeInterval 3.0  

    @interface RootViewController ()<UITableViewDelegate,UITableViewDataSource>  

    @property(nonatomic, retain)NSTimer *timer;  

    @property(nonatomic, retain)UITableView    *tableView;  

    @property(nonatomic, retain)model *model;  

    @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];  

            NSDictionary *dic = [NSDictionary dictionaryWithObject:[NSMutableArray arrayWithCapacity:0] forKey:@"modelArray"];  

            self.model = [[model alloc] initWithDic:dic];  

    - (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  

    -(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 

KVO

繼續閱讀