ios kvo 怎么得知其值不再变化

 我来答
好程序员
2016-01-26 · HTML5前端培训/大数据培训/Java
好程序员
好程序员是IT高端课程培训基地,从平凡到卓越,为梦想而拼搏。
向TA提问
展开全部
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
//
// 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相关

[objc] view plain copy
//
// 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
o羞涩的狼o
2016-01-21 · 超过19用户采纳过TA的回答
知道答主
回答量:81
采纳率:0%
帮助的人:43.2万
展开全部
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)contex{}
每次变化都会调用这个方法的啊

只要你检测了 不变化 就不调这个方法
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式