KVC(NSKeyValueCoding)键值编码
1.定义:间接访问对象属性(用于字符串表征)的机制,而不是直接通过调用访问器或点语法去访问对象的属性。
2.KVC把对象属性编码成相应字符串,通过字符串设置访问属性。(等价于将属性变成key和value的形式,类似于字典,注意不要混淆成字典的方法)
3.当类里面没有定义属性或不知道类里面是什么属性的时候使用KVC。
4.通过KVC可以访问成员变量(_下划线),但直接访问@"_属性名"(破坏了封装的特性)没有做正确性校验,所以通常@"属性名"。通过KVC也可以设置访问私有成员变量,总的来说可以设置访问所有属性。
KVO(NSKeyValueObserving)键值监听
1.定义:当对象属性发生变化,我们能收到一个"通知";起监听属性的作用。
2.KVO是基于KVC的,NSObject类为所以对象提供一个自动观察机制(也可以自己监听自己)。
3.步骤:
- 注册监听对象属性
- 实现回调方法(当属性发生改变,系统自动调用)
- 移除
上下文(context):上文与下文的联系。通过上下文可以传值,是C语言的概念(void *),万能指针可以传任何东西,常用传数组.
Observer:监听者
options:有4种可能选择,用|选择多种。
通知(面对熟悉的人群,代理的话是面对陌生者)
1.通知一般用于MVC间信息传递,如设置页面app换肤(1对多传值)。
2.通知发送(NSNotification)
- name:通知的名字,xxx通知(唯一的)
- userinfo:内容(用字典存)
- object:发送者,xxx发送(通常不太关心)
3.通知中心(NSNotificationCenter):单例,作中转站,统一管理。
- 注册和移除都是放生在监听者身上。
- 通知发送写在其它类。
4.作用:通知用于2各不相关的类之间传值。
5.特点:广播式(1个类到通知中心向多个监听者传播)
6.目标-动作机制
目标是动作消息的接收者。一个控件,或者更为常见的是它的单元,以插座变量(参见”插座变量”部分)
的形式保有其动作消息的目标。
动作是控件发送给目标的消息,或者从目标的角度看,它是目标为了响应动作而实现的方法。
程序需要某些机制来进行事件和指令的翻译。这个机制就是目标-动作机制。
kvc&&kvo
Teacher.h
#import <Foundation/Foundation.h> @interface Teacher : NSObject { NSString *_name; int _age; @private NSString *count; } @property(nonatomic,retain)NSString *name; @property(nonatomic,assign)int age; @end
Teacher.m
#import "Teacher.h" @implementation Teacher @synthesize name = _name,age = _age; -(id)init//因为当自己监听自己,所以在这里写 { self = [super init]; if (self) { //注册监听name属性 [self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld//枚举 context:@"123"];//数组传多个值 //注册监听age属性。。。 } return self; } //当属性发生变时候,此方法自动调用 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { NSLog(@"keyPath = %@",keyPath); NSLog(@"object = %@",object); NSLog(@"change = %@",change); NSLog(@"context = %@",context); } -(void)dealloc { [_name release]; [count release]; [super dealloc]; } @end
AppDelegate.m
//Teacher *t = [[Teacher alloc]init]; /* [t setValue:@"jobs" forKey:@"_name"]; NSLog(@"%@",[t valueForKey:@"_name"]); [t setValue:[NSNumber numberWithInt:18] forKey:@"_age"]; NSLog(@"%@",[t valueForKey:@"_age"]); // [t setValue:@"28" forKey:@"count"]; NSLog(@"%@",[t valueForKey:@"count"]); */ /* //kvo t.name = @"obanma"; t.name = @"jobs"; */
通知
Student.h
#import <Foundation/Foundation.h> @interface Student : NSObject { NSString *_name; } @property(nonatomic,retain)NSString *name; @end
Student.m
#import "Student.h" @implementation Student @synthesize name = _name; -(id)init { self = [super init]; if (self) { //到通知中心注册 NSNotificationCenter *center = nil; center = [NSNotificationCenter defaultCenter]; //获取通知中心,唯一的 //监听者注册 [center addObserver:self //监听者 selector:@selector(goHome:) name:@"GO_HOME_NOTIONIFICATION"//唯一 object:nil]; //发送者 } return self; } -(void)goHome:(NSNotification *)aNoti//target-ation机制 { //收到通知的内容 NSDictionary *dic = [aNoti userInfo]; NSString *date = [dic valueForKey:@"date"]; NSString *time = [dic valueForKey:@"time"]; NSLog(@"%@ go home at %@,%@",self.name,date,time); } -(void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:@"GO_HOME_NOTIONIFICATION" object:nil]; [_name release]; [super dealloc]; } @end
Master.h
#import <Foundation/Foundation.h> @interface Master : NSObject { NSString *_name; } @property(nonatomic,retain)NSString *name; -(void)furlough; @end
Master.m
#import "Master.h" @implementation Master @synthesize name = _name; //发送 -(void)furlough { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; //字典内容 NSDictionary * dic = [NSDictionary dictionaryWithObjectsAndKeys:@"24",@"date",@"6:00",@"time", nil]; [center postNotificationName:@"GO_HOME_NOTIONIFICATION" object:nil userInfo:dic]; } -(void)dealloc { [_name release]; [super dealloc]; } @end
AppDelegate.m
//通知 Master *s = [[Master alloc]init]; Student *s1 = [[Student alloc]init]; s1.name = @"jobs"; Student *s2 = [[Student alloc]init]; s2.name = @"bill"; [s furlough];
kvo手动监听属性和自动监听属性
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self addObserver:self forKeyPath:@"num" options:NSKeyValueObservingOptionNew context:nil]; } - (IBAction)changeValueAction:(id)sender { //手动通知在需要改变值num变量的地方 [self willChangeValueForKey:@"num"]; self.num = 2; [self didChangeValueForKey:@"num"]; } //当设置为手动的时候如果不调用willChangeValueForKey:didChangeValueForKey:的情况,observeValueForKeyPath:不会调用 +(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key{ //设置是否自动监听属性 if ([key isEqualToString:@"num"]) { return NO;//手动监听num } return [super automaticallyNotifiesObserversForKey:key]; } //系统监听属性变化方法 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"num" ]) { NSInteger targetNum = [[change objectForKey:NSKeyValueChangeNewKey]integerValue]; NSLog(@"num = %ld",targetNum); }else{ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } -(void)dealloc{ [self removeObserver:self forKeyPath:@"num" context:nil]; }