iOS开发之KVC、KVO
来源:互联网 发布:淘宝里的天猫店 编辑:程序博客网 时间:2024/05/17 08:28
在此声明:此内容是之前在网上查找的例子自己下去练习写的Demo,原文地址已忘记,若有雷同,还请原作谅解。若内容有不足之处,还请大家多多指教。
KVO
一,概述
KVO,即:Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者了。
二,使用方法
系统框架已经支持KVO,所以程序员在使用的时候非常简单。
1. 注册,指定被观察者的属性,
2. 实现回调方法
3. 移除观察
三,实例:
假设一个场景,股票的价格显示在当前屏幕上,当股票价格更改的时候,实时显示更新其价格。
四, 模式
KVO也分2种,一种是自动的KVO,一种是手动的KVO。
NSObject自动支持KVO特性并且默认情况下一个类的属性支持kvc都可以使用。如果你遵循标准的Cocoa编码和命名规则,你可以使用自动更改通知你不需要写任何额外的代码。手动更改通知提供额外的控制时发出的通知,并要求额外的编码。你可以通过类的方法automaticallynotifiesobserversforkey:控制您的类属性自动通知。
自动模式的KVO:NSObject提供了基本的自动键-值改变通知。
手动模式的KVO:实现手动通知的对象必须实现 automaticallyNotifiesObserversForKey 方法。为了实现手动观察消息,你必须在改变值之前调用 willChangeValueForKey: ,改变值之后调用 didChangeValueForKey:
附上代码:
StockData.h
#import <Foundation/Foundation.h>
// stock 股票
@interface StockData : NSObject
{
NSString *stockName;//股票名
float price;//股票价格
}
@end
Walker.h
#import <Foundation/Foundation.h>
@interface Walker : NSObject
{
NSString *_name;
int _age;
}
@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)int age;
-(instancetype)initWithName:(NSString *)name age:(int)age;
@end
Walker.m
#import "Walker.h"
@implementation Walker
-(instancetype)initWithName:(NSString *)name age:(int)age
{
if (self = [super init])
{
_name=name;
_age=age;
}
return self;
}
@end
#import "ViewController.h"
#import "StockData.h"
#import "Walker.h"
@interface ViewController ()
{
StockData *_stockKVO;
UILabel *_myLabel;
Walker *_walker;
UILabel *_ageLabel;
UIButton * btn;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initStock];
[self initWalker];
btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(40, 60, 200, 80);
[btn setTitle:@"百变大咖秀" forState:UIControlStateNormal];
btn.backgroundColor=[UIColor greenColor];
[btn addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
// 股票信息
- (void)initStock
{
_stockKVO = [[StockData alloc] init];
[_stockKVO setValue:@"东方航空" forKey:@"stockName"];
[_stockKVO setValue:@"200" forKey:@"price"];
NSLog(@"stockName===%@",[_stockKVO valueForKey:@"stockName"]);
NSLog(@"price===%@",[_stockKVO valueForKey:@"price"]);
// 1 注册监听
[_stockKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
_myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 300, 100, 40 )];
_myLabel.backgroundColor = [UIColor grayColor];
_myLabel.text = [NSString stringWithFormat:@"股票:%@",[_stockKVO valueForKey:@"price"]];
[self.view addSubview:_myLabel];
}
// 年龄
- (void)initWalker
{
_walker = [[Walker alloc] initWithName:@"JohnSon" age:22];
[_walker addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
_ageLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 400, 100, 40 )];
_ageLabel.backgroundColor = [UIColor redColor];
_ageLabel.text = [NSString stringWithFormat:@"年龄:%@",[_walker valueForKey:@"age"]];
[self.view addSubview:_ageLabel];
}
//当点击button的时候,调用buttonAction方法,修改对象的属性
-(void) buttonAction
{
[_stockKVO setValue:@"20000.0" forKey:@"price"];
_walker.age-=2;
}
// 2. 实现回调方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"price"])
{
_myLabel.text = [NSString stringWithFormat:@"%@",[_stockKVO valueForKey:@"price"]];
_ageLabel.text = [NSString stringWithFormat:@"%@",[_walker valueForKey:@"age"]];
}
}
KVC
KVC是KeyValue Coding的简称,它是一种可以直接通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。
2.2.1 获取值
valueForKey:,传入NSString属性的名字。
valueForKeyPath:,传入NSString属性的路径,xx.xx形式。
valueForUndefinedKey它的默认实现是抛出异常,可以重写这个函数做错误处理。
2.2.2 修改值
setValue:forKey:
setValue:forKeyPath:
setValue:forUndefinedKey:
setNilValueForKey: 当对非类对象属性设置nil时,调用,默认抛出异常。
2.2.3 一对多关系成员的情况
mutableArrayValueForKey:有序一对多关系成员 NSArray
mutableSetValueForKey:无序一对多关系成员 NSSet
Book.h
#import <Foundation/Foundation.h>
@class Author;
@interface Book : NSObject
{
NSString *name;
Author *author;
float price;
NSArray *relativeBooks;
}
@end
Author.h
#import <Foundation/Foundation.h>
@interface Author : NSObject
{
NSString *authorName;
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
//示例1:基本赋值取值
Book *book = [[Book alloc] init];
[book setValue:@"书名叫:《Objective-C入门》" forKey:@"name"];
// 取值
NSString *name = [book valueForKey:@"name"];
NSLog(@"name===%@",name);
//示例2:使用路径 valueForKeyPath
Author *author = [[Author alloc] init];
[author setValue:@"作者名叫:JohnSon" forKey:@"authorName"];
[book setValue:author forKey:@"author"];
NSString *authorName = [book valueForKeyPath:@"author.authorName"];
NSLog(@"authorName===%@",authorName);
// 示例3:自动装箱拆箱
// KVC还有一个很重要的特点,自动装箱拆箱功能。这在ObjC中是仅有的,其他情况下均需要使用比如NSNumber来手动拆装箱的。
[book setValue:author forKey:@"author"];
[book setValue:@"张三" forKeyPath:@"author.authorName"];
[book setValue:@"100" forKey:@"price"];
NSString *bookPrice = [book valueForKey:@"price"];
NSLog(@"book price is %@",bookPrice);
/**
输出结果为:2015-01-28 11:37:45.086 KVC[4320:68554] book price is 100
可以看到给bookPrice输入的是NSString类型,但是没有问题,因为KVC方式会根据字符串自动转型为适当的数值。再看打印bookPrice属性,%@是打印对象,而price属性是float基本型,这里KVC肯定做了自动装箱的处理,将基本型转为NSNumber对象。
*/
// 示例4:对集合的操作能力
// KVC还具备对集合的操作能力。比如,图书可以有相关图书,这是个1对多的关系。可以用集合来表示,这里用NSArray表示
// 如果想得到相关图书的价格NSArray,可以使用KVC方式
Book *book1 = [[Book alloc] init];
[book1 setValue:@"20" forKey:@"price"];
Book *book2 = [[Book alloc] init];
[book2 setValue:@"30" forKey:@"price"];
NSArray *bookPrices = [NSArray arrayWithObjects:book1,book2, nil];
[book setValue:bookPrices forKey:@"relativeBooks"];
NSString *booksPrice = [book valueForKeyPath:@"relativeBooks.price"];
NSLog(@"relative books price: %@",booksPrice);
// 示例5:对集合做运算
// KVC还能对集合做运算,比如想得到相关图书的个数、相关图书的价格总和、相关图书的平均价格、价格的最大值和价格的最小值
NSLog(@"relative books price: %@",[book valueForKeyPath:@"relativeBooks.price"]);
NSLog(@"relative books count: %@",[book valueForKeyPath:@"relativeBooks.@count"]);
NSLog(@"relative books price sum: %@",[book valueForKeyPath:@"relativeBooks.@sum.price"]);
NSLog(@"relative books price avg: %@",[book valueForKeyPath:@"relativeBooks.@avg.price"]);
NSLog(@"relative books price max: %@",[book valueForKeyPath:@"relativeBooks.@max.price"]);
NSLog(@"relative books price min: %@",[book valueForKeyPath:@"relativeBooks.@min.price"]);
//另外,如果想获得没有重复的价格集合,可以这样:在使用@distinctUnionOfObjects后,发现效果是消除重复的价格。
NSLog(@"relative books distinct price: %@",[book valueForKeyPath:@"relativeBooks.@distinctUnionOfObjects.price"]);
// 示例6:更多用法
// KVC还可以在一个语句中为实例的多个属性赋值:
Book *book4=[[Book alloc] init];
NSArray *bookProperties=[NSArray arrayWithObjects:@"name",@"price",nil];
NSDictionary *bookPropertiesDictionary=[book4 dictionaryWithValuesForKeys:bookProperties];
NSLog(@"book values: %@",bookPropertiesDictionary);
NSDictionary *newBookPropertiesDictionary=[NSDictionary dictionaryWithObjectsAndKeys:@"《Objective C入门》",@"name", @"20.5",@"price",nil];
[book4 setValuesForKeysWithDictionary:newBookPropertiesDictionary];
NSLog(@"book with new values: %@",[book4 dictionaryWithValuesForKeys:bookProperties]);
//另外,还有两个比较高级的内容:nil和覆盖setNilValueForKey方法,覆盖valueForUndefinedKey方法,可自行看reference了解。
}
- iOS开发之KVC、KVO
- iOS开发之KVC/KVO
- 12、iOS 开发之 KVC \KVO
- iOS开发之 KVC,KVO简单了解
- iOS开发UI系列之KVC/KVO
- iOS开发之KVC与KVO
- iOS开发之通知中心、KVC、KVO
- iOS开发--KVC & KVO
- iOS开发 - KVO/KVC
- IOS 之 KVC & KVO
- iOS开发:KVO和KVC
- iOS开发 KVC和KVO
- IOS开发 - KVC 和 KVO
- 【iOS开发系列】KVC&KVO
- iOS开发:KVO和KVC
- iOS之KVC和KVO
- iOS之KVC和KVO
- iOS之KVC和KVO
- poj1269 直线求交点
- 自制OS 第7步
- 欢迎使用CSDN-markdown编辑器
- 23种设计模式(15):迭代器模式
- Android measure 简单理解
- iOS开发之KVC、KVO
- V8引擎之Binding
- LeetCode--Next Permutation
- myplan
- 【张孝祥并发课程笔记】14:java5阻塞队列的应用
- 搜索推广营销五步曲之三:方案制作之如何写好创意
- 项目总结之优化游戏包大小
- 动态路由距离矢量路由协议RIP
- hdu 4288 线段树+离散化