KVC(Key Value Coding)--鍵值編碼:是間接訪問(wèn)實(shí)例變量的方式妆绞。指的是在iOS的開(kāi)發(fā)中可以允許開(kāi)發(fā)者通過(guò)Key名直接訪問(wèn)對(duì)象的屬性,或者給對(duì)象的屬性賦值必搞。而不需要調(diào)用明確的存取方法必指。這樣就可以在運(yùn)行時(shí)動(dòng)態(tài)地訪問(wèn)和修改對(duì)象的屬性。而不是在編譯時(shí)確定恕洲,這是iOS開(kāi)發(fā)中的黑魔法之一塔橡。
使用KVC為對(duì)應(yīng)的實(shí)例變量賦值的過(guò)程調(diào)用setValue:forKey:
賦值原理:給定一個(gè)key(字符串),比如name:
(1)先查對(duì)象中是否存在對(duì)應(yīng)的setName:方法,如果有調(diào)用該方法為實(shí)例變量賦值,否則轉(zhuǎn)第二步
(2)查對(duì)象中是否存在對(duì)應(yīng)的_name的實(shí)例變量,如果有直接取出該實(shí)例變量,否則轉(zhuǎn)步奏(3)
(3)查找對(duì)象中有沒(méi)有對(duì)應(yīng)的實(shí)例變量叫做name,如果有直接為實(shí)例變量賦值,否則轉(zhuǎn)步奏(4)
(4)自動(dòng)調(diào)用對(duì)象中的方法: setVAlue:forUndefinedKey:,將沒(méi)有找到的鍵輸出
KVC取值過(guò)程原理:valueForKey:,給定一個(gè)鍵key比如name:
(1)先查對(duì)象中是否存在對(duì)應(yīng)的getter:方法研侣,如果有直接調(diào)用谱邪,返回實(shí)例變量的內(nèi)容,否則轉(zhuǎn)第二步
(2)查對(duì)象中是否存在對(duì)應(yīng)的_name的實(shí)例變量,如果有直接返回實(shí)例變量的內(nèi)容庶诡,否則轉(zhuǎn)第三步
(3)查找對(duì)象中有沒(méi)有對(duì)應(yīng)的實(shí)例變量叫做name,如果有直接返回實(shí)例變量的內(nèi)容,否則轉(zhuǎn)步驟4
(4)系統(tǒng)自動(dòng)調(diào)用valueForUndefinedKey:,方法詢問(wèn)應(yīng)該返回何種類型的對(duì)象
Demo
main.m
//
// main.m
// WSKVC
//
// Created by ws on 15/9/23.
//
#import <Foundation/Foundation.h>
#import "Nurse.h"
#import "Sick.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//創(chuàng)建一個(gè)小護(hù)士
Nurse *nurse = [[Nurse alloc]init];
[nurse setValue:@"tt" forKey:@"name"];
[nurse setValue:@"女" forKey:@"gender"];
[nurse setValue:@90 forKey:@"age"];
[nurse ws_intrduction];
//創(chuàng)建一個(gè)病人對(duì)象
Sick *sick = [[Sick alloc]init];
[nurse setValue:sick forKey:@"sick"];
[nurse setValue:@"gg" forKeyPath:@"sick.name"];
[nurse setValue:@"男" forKeyPath:@"sick.gender"];
[nurse setValue:@90 forKeyPath:@"sick.age"];
[sick ws_intrduction];
/**
KVC獲取實(shí)例變量的內(nèi)容
*/
NSString *nurseName = [sick valueForKey:@"name"];
NSLog(@"%@",nurseName);
NSString *sickName = [sick valueForKeyPath:@"sick.name"];
NSLog(@"%@",sickName);
}
return 0;
}
Nurse.h
//
// Nurse.h
// WSKVC
//
// Created by ws on 15/9/23.
//
#import <Foundation/Foundation.h>
@class Sick;
@interface Nurse : NSObject{
NSString *_name;
NSString *_gender;
NSNumber *_age;
Sick *_sick;//存儲(chǔ)一個(gè)病人對(duì)象
}
-(void)ws_intrduction;
@end
Nurse.m
//
// Nurse.m
// WSKVC
//
// Created by ws on 15/9/23.
//
#import "Nurse.h"
#import "Sick.h"
@implementation Nurse
-(void)ws_intrduction{
NSLog(@"%@ %@ %@", _name,_gender,_age);
}
//KVC賦值過(guò)程中如果沒(méi)有發(fā)現(xiàn)某個(gè)key惦银,該方法會(huì)被系統(tǒng)自動(dòng)調(diào)用,輸出沒(méi)有發(fā)現(xiàn)的key和key對(duì)應(yīng)的value值
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"------%@--%@",value ,key);
}
//KVC取值過(guò)程中如果沒(méi)有發(fā)現(xiàn)某個(gè)key末誓,該方法會(huì)被系統(tǒng)自動(dòng)調(diào)用扯俱,詢問(wèn)需要返回什么對(duì)象,一般返回nil
-(id)valueForUndefinedKey:(NSString *)key{
//nil:代表OC中的空對(duì)象
return nil;
}
@end
Sick.h
//
// Sick.h
// WSKVC
//
// Created by ws on 15/9/23.
//
#import <Foundation/Foundation.h>
@interface Sick : NSObject{
NSString *_name;
NSString *_gender;
NSNumber *_age;
}
-(void)ws_intrduction;
@end
Sick.m
//
// Sick.m
// WSKVC
//
// Created by ws on 15/9/23.
//
#import "Sick.h"
@implementation Sick
-(void)ws_intrduction{
NSLog(@"%@ %@ %@",_name,_gender,_age);
}
@end