美文网首页面试题目
iOS KVO方式监听数组变化方法

iOS KVO方式监听数组变化方法

作者: JasonEVA | 来源:发表于2016-04-21 17:09 被阅读2164次

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

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

    /*

    *  第一步 建立观察者及观察的对象
    
    *  第二步 处理key的变化(根据key的变化刷新UI)
    
    *  第三步 移除观察者
    

    */

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

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

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

    [objc] view plain copy
    @interface model : NSObject
    @property(nonatomic, copy)NSString *name;
    @property(nonatomic, retain)NSMutableArray *modelArray;

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

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

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

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

    [objc] view plain copy
    不能这样 [_model.modelArray addObject]方法,需要这样调用 [[_model mutableArrayValueForKey:@"modelArray"] addObject:str];原因稍后说明。
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

    [objc] view plain copy
    {
    if ([keyPath isEqualToString:@"modelArray"]) {
    [_tableView reloadData];
    }
    }

    第三步 移除观察者
    

    [objc] view plain copy
    if (_model != nil) {
    [_model removeObserver:self forKeyPath:@"modelArray"];
    }

    以下附上本文代码:
    代码中涉及三点

    1 根据数组动态刷新tableview;

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

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

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

    1 NSTimer相关

    [objc] view plain copy
    //
    // 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

    [objc] view plain copy
    //
    // 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相关
    [objc] view plain copy

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

    [objc] view plain copy
    //
    // model.m
    // KVOTableview
    //
    //

    //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  
      
    /* 
        *  第一步 建立观察者及观察的对象 
        *  第二步 处理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
    

    相关文章

      网友评论

        本文标题:iOS KVO方式监听数组变化方法

        本文链接:https://www.haomeiwen.com/subject/drbtrttx.html