键值观察就是对象属性表换透明的通知观察者的一种机制。它是通知某些对象关于其他对象的属性值发生变化的一种机制。不需要对被观察者的Class进行修改,永远是观察你的类做事情。
这里主要实现一个无论对象什么时候发生变化,都可以让表格单元自动更新。观察者为self.object,被观察的对象属性为self.property。
#import <UIKit/UIKit.h>
@interface TableViewCell : UITableViewCell
-(id)initWithReuseIdentifer:(NSString *) identifier;
@property (nonatomic, readwrite,strong) id object;
@property (nonatomic,readwrite,copy) NSString *property;
@end
#import "TableViewCell.h"
@implementation TableViewCell
-(BOOL)isReady
{
return (self.object && [self.property length] > 0);
}
-(void)update
{
NSString *text;
if (self.isReady) {
id value = [self.object valueForKeyPath:self.property];
text = [value description];
} else {
text = @"";
}
self.textLabel.text = text;
}
-(id)initWithReuseIdentifer:(NSString *) identifier
{
return [self initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
-(void)removeObservation
{
if (self.isReady) {
[self.object removeObserver:self forKeyPath:self.property];
}
}
-(void)addObservation {
if (self.isReady) {
//self.object为表格控制器,将self作为context指针传递,以便在回调函数observeValueForKeyPath中可以判断这是我们观察的事件
[self.object addObserver:self forKeyPath:self.property options:0 context:(void *)self];
}
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if ((__bridge id)context == self) {
[self update];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
-(void)dealloc
{
if (_object && [_property length] > 0) {
[_object removeObserver:self forKeyPath:_property context:(__bridge void * _Nullable)(self)];
}
}
-(void)setObject:(id)object
{
[self removeObservation];
_object = object;
[self addObservation];
[self update];
}
-(void)setProperty:(NSString *)property
{
[self removeObservation];
_property = property;
[self addObservation];
[self update];
}
@end
控制器代码
#import "TableViewController.h"
#import "TableViewCell.h"
@interface TableViewController ()
@property(nonatomic,retain) NSTimer *timer;
@property (readwrite,retain ) NSDate *now;
@end
@implementation TableViewController
-(void)updataNow {
self.now = [NSDate date];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.timer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(updataNow) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 100;
}
- (TableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//注意自定义TableViewCell的时,Xib文件不要在设置CellIdentifier
static NSString *CellIdentifier = @"wubiao";
TableViewCell *wubiaoCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (wubiaoCell == nil) {
wubiaoCell = [[TableViewCell alloc] initWithReuseIdentifer:CellIdentifier];
wubiaoCell.backgroundColor = [UIColor greenColor];
[wubiaoCell setProperty:@"now"];
[wubiaoCell setObject:self];
}
return wubiaoCell;
}
-(void)dealloc
{
self.timer = nil;
self.now =nil;
}
@end