寫作本文來由: 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