KVO监听UI控件的frame变化,kVO的简单使用,KVC的初步了解
来源:互联网 发布:linux nfsnobody 编辑:程序博客网 时间:2024/05/17 05:07
一、KVO
KVO的是KeyValue Observe的缩写,中文是键值观察。这是一个典型的观察者模式,利用它可以很容易使用实现视图组件和数据模型的分离,当数据模型的属性值改变之后作为监听器的视图组件就会被激发,激发时就会回调监听器自身,在Objc中实现KVO则必须实现NSKeyValueObServing协议,不过幸运的是NSObject已经实现了该协议,因此几乎所哟的NSObjectd对象都可以使用KVO。iOS中有个Notification的机制,也可以获得通知,但这个机制需要有个Center,相比之下KVO更加简洁而直接。
KVO的使用也很简单,就是简单的3步。
1.注册需要观察的对象的属性addObserver:forKeyPath:options:context:
2.实现observeValueForKeyPath:ofObject:change:context:方法,这个方法当观察的属性变化时会自动调用
3.取消注册观察removeObserver:forKeyPath:context:
这里有两种方式,一种是匹配keyPath,另一种是使用context
Demo:事列
A.注册需要观察的对象
- (void)viewDidLoad{ [super viewDidLoad]; // 注册监听 [self.moveView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; self.p.name = @"小明"; [self.p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:PersonAgeContext];}
B.实现
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ // 方式1.匹配keypath if ([keyPath isEqualToString:@"frame"]) { NSLog(@"self.moveView.y = %f", self.moveView.y); } // 方式2.上下午 if (context == PersonAgeContext) { NSLog(@"%@%d岁了", self.p.name, self.p.age); }}
C.移除监听
-(void)dealloc // ARC模式下{ [self.moveView removeObserver:self forKeyPath:@"frame"]; [self.p removeObserver:self forKeyPath:@"age" context:PersonAgeContext];}
KVO的 优势 :
1.能够提供一种简单的方法实现两个对象间的同步。例如:model和view之间同步;
2.能够对非我们创建的对象,即内部对象的状态改变作出响应,而且不需要改变内部对象(SKD对象)的实现;
3.能够提供观察的属性的最新值以及先前值;
4.用key paths来观察属性,因此也可以观察嵌套对象;
5.完成了对观察对象的抽象,因为不需要额外的代码来允许观察值能够被观察
缺点 :
1.我们观察的属性必须使用strings来定义。因此在编译器不会出现警告以及检查;
2.对属性重构将导致我们的观察代码不再可用;
3.复杂的“IF”语句要求对象正在观察多个值。这是因为所有的观察代码通过一个方法来指向;
4.当释放观察者时不需要移除观察者。
二、KVC
1、KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性。而不是通过调用Setter、Getter方法访问。KVO 就是基于 KVC 实现的关键技术之一。
KVC的操作方法由NSKeyValueCoding协议提供,而NSObject就实现了这个协议,也就是说ObjC中几乎所有的对象都支持KVC操作,常用的KVC操作方法如下:
- 动态设置: setValue:属性值 forKey:属性名(用于简单路径)、setValue:属性值 forKeyPath:属性路径(用于复合路径,例如Person有一个Account类型的属性,那么person.account就是一个复合属性)
- 动态读取: valueForKey:属性名 、valueForKeyPath:属性名(用于复合路径)
Student.h
#import <Foundation/Foundation.h>@class Teacher;@interface Student : NSObject{ NSString *_nickName;}@property (nonatomic, copy) NSString *name;@property (nonatomic, strong) Teacher *teacher;@endStudent.m
#import "Student.h"#import "Teacher.h"@mplementation Student- (instancetype)init{ if (self = [super init]) { _nickName = @"小样"; } return self;}- (void)setTeacher:(Teacher *)teacher{ _teacher = teacher; //注册一个KVO //第三个参数, NSKeyValueObservingOptionNew 获取最新改变后的值 //NSKeyValueObservingOptionOld 获取改变之前的值 //同时多个值都要传递 中间使用 | [self.teacher addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil]; /* 0x01 | 0x02 0000 0001 0000 0010 0000 0011 0x03 */}//#define KeyName @"name"//extern NSString *const KeyName; 一般在头文件声明//static NSString *const KeyName = @"name"; 在实现文件进行赋值//实现监听方法- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ //由哪个kvo发过来的监听 if ([keyPath isEqualToString:@"name"]) { //通过字典获取改变后的值 NSString *string = [change objectForKey:NSKeyValueChangeNewKey]; NSLog(@"newKeyPath:%@", string); }}- (void)dealloc{ //注销监听 [self.teacher removeObserver:self forKeyPath:@"name"]; //ARC环境下重写dealloc,不要实现[super dealloc]// [super dealloc];}
Teacher.h
#import <Foundation/Foundation.h>@interface Teacher : NSObject@property (nonatomic, copy) NSString *name;- (void)changeName;@end
Teacher.m
#import "Teacher.h"@implementation Teacher- (void)changeName{ _name = @"hahaha";}@endmain.m
int main(int argc, const char * argv[]) { @autoreleasepool { Student *student = [[Student alloc] init]; student.name = @"Jobs"; //通过kvc的方式给变量赋值 [student setValue:@"Gates" forKey:@"name"]; //KVC key-value Coding 键值编码 NSLog(@"%@", [student valueForKey:@"name"]); [student setValue:@"nickName" forKey:@"nickName"]; NSLog(@"%@", [student valueForKey:@"nickName"]); NSArray *array = @[student]; //OC 动态绑定的特性 for (id obj in array) { NSLog(@"%@", [obj valueForKey:@"name"]); } //KVO key-value observer 键值观察者 /* 1.注册一个kvo监听 2.实现监听方法 3.注销kvo监听 MVC 可读性,可维护性,可移植性 model 数据模型 controller 控制器 view 视图 */ //!!只有通过setter方法进行修改的时候,才能使用kvo的监听!! Teacher *teacher = [[Teacher alloc] init]; student.teacher = teacher; teacher.name = @"teacher1"; teacher.name = @"teacher2"; [teacher changeName]; NSLog(@"%@", teacher.name); } return 0;}打印结果:
在Student类中有一个_nickName的属性,但是没有提供任何getter/setter的访问方法。同时在main.m里面有一个Student的对象指针。
当Student实例化后,常规来说是无法访问这个对象的_nickName属性的,不过通过KVC我们做到了,在打印里有输出信息,这就说明确实读写了_nickName属性
KVC的常用方法:
- (id)valueForKey:(NSString *)key; -(void)setValue:(id)value forKey:(NSString *)key;
valueForKey的方法根据key的值读取对象的属性,setValue:forKey:是根据key的值来写对象的属性。
注意:
(1). key的值必须正确,如果拼写错误,会出现异常
(2). 当key的值是没有定义的,valueForUndefinedKey:这个方法会被调用,如果你自己写了这个方法,key的值出错就会调用到这里来
(3). 因为类key反复嵌套,所以有个keyPath的概念,keyPath就是用.号来把一个一个key链接起来,这样就可以根据这个路径访问下去
(4). NSArray/NSSet等都支持KVC
- KVO监听UI控件的frame变化,kVO的简单使用,KVC的初步了解
- 初步了解KVO的使用
- KVC 和 KVO 监听容器类(数组等)的变化
- iOS KVC与KVO的简单使用
- KVO/KVC简单的介绍
- KVO & KVC 的比较 - KVO
- ios KVC KVO的使用
- KVC 和KVO的使用
- KVC和KVO的使用
- kvc和kvo的使用情况的了解
- KVO与KVC键值监听的机制
- IPHONE 和 KVC/KVO 监听对象属性变化(例如:获取textView 的text的变化)
- IPHONE 和 KVC/KVO 监听对象属性变化(例如:获取textView 的text的变化)
- [iOS KVO监控view的frame变化]
- KVO/KVC的理解
- KVO/KVC的理解
- KVC、KVO的用法
- KVO/KVC的demo
- linux中的各种计算方式expr|bc|dc|let
- 2015年终总结
- 数据库第二章
- SSH Connection refused
- STM32的位带操作
- KVO监听UI控件的frame变化,kVO的简单使用,KVC的初步了解
- 使用AlertDialog创建对话框
- 饭一口一口吃,路一步一步走
- 使用 宏定义 实现的高级算法
- Ubuntu配置静态ip
- 机器学习心得(一)
- Mac平台下使用nm命令查看文件的符号表
- markdown使用手册(自己收藏用的)
- mysql