iOS KVC_KVO_Archiver

KVC

KVC称为键-值编码(key value coding),一种以字符串标识符间接访问属性的机制


对于kvc机制如何通过key寻找到value:

当通过KVC调用对象时,比如:[self valueForKey:@”someKey”]时,程序会自动试图通过几种不同的方式解析这个调用。

1.首先查找对象是否带有 someKey 这个方法

2.如果没找到,会继续查找对象是否带有someKey这个实例变量(iVar)

3.如果还没有找到,程序会继续试图调用 -(id) valueForUndefinedKey:这个方法。

4.如果这个方法还是没有被实现的话,程序会抛出一个NSUndefinedKeyException异常错误。

(Key-Value Coding查找方法的时候,不仅仅会查找someKey这个方法,还会查找getsomeKey这个方法,前面加一个get,或者_someKey以及_getsomeKey这几种形式。同时,查找实例变量的时候也会不仅仅查找someKey这个变量,也会查找_someKey这个变量是否存在。)

设计valueForUndefinedKey:方法的主要目的是当你使用-(id)valueForKey方法从对象中请求值时,对象能够在错误发生前,有最后的机会响应这个请求。


// 设置值:setValue:forKey: 

// 获取值: valueForKey:    

[car setValue:@"BMW2.0" forKey:@"type"];

NSLog(@"type = %@",[car valueForKey:@"type"]);

//注意: 对基本类型使用kvc存储NSNumber

[car setValue:@23.4 forKey:@"speed"];

NSLog(@"speed = %f",[[car valueForKey:@"speed"] doubleValue]);

//注意: 出现问题, key在对象不存在,崩溃

[car setValue:@"123” forKey:@"test"];


//keyPath的使用

//需求: 使用KVC设置car的engine的power为300

[car setValue:@300.0 forKeyPath:@"engine.power"];

NSLog(@"power = %f",[[car valueForKeyPath:@"engine.power"] doubleValue]);


//字典转化为对象setValuesForKeysWithDictionary

NSDictionary *carDict = @{@"type":@"Santana",@"speed":@12};

[car setValuesForKeysWithDictionary:carDict];

NSLog(@"type = %@,speed=%f",car.type,car.speed);


//KVC的原理

[car mySetValue:@"benz" forKey:@"type"];

//实现系统和setValue:forKey方法

-(void)mySetValue:(id)object forKey:(NSString *)key

{

    //思路: 

    //1.根据字符串生成 setType:方法

    //2.调用这个方法

    NSString *methodName = [NSString stringWithFormat:@"set%@:",[key capitalizedString]];

    SEL sel = NSSelectorFromString(methodName);

    [self performSelector:sel withObject:object];

}


KVO

KVO称为键-值监听(key value observing),观察某个属性的变化的机制,当某个属性一旦改变,可以立即观察到这个属性的改变


//实时观察到车速的改变

car.speed = 0;

//添加对于speed属性的监听

//关键方法: addObserver

//作用: 一旦@"speed"对应属性从旧值变为新值, self对象发送消息(方法名是固定的)

[car addObserver:self forKeyPath:@"speed" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];

//只有在使用set方法时候KVO才能起效

car.speed = 100;

car.speed = 200;

//addObserver 必须在结束之后移除监听

[car removeObserver:self forKeyPath:@"speed"];


//这个方法是kvo的监听处理方法

//参数1: 表示哪个属性改变了

//参数2: 表示哪个对象的属性改变了

//参数3: 表示如何改变的

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context

{

    //获取改变值, 使用KVC获取这个值

    double speed = [[object valueForKeyPath:keyPath] doubleValue];

    NSLog(@"speed = %f",speed);

}


Archiver

archiver即归档:数据持久化(把数据保存到文件中) 

保存方式:文件, plist,数据库,NSUserDefault

为了把对象存储到文件,存储方式最好选用归档


//系统对象的归档

//需求: 保存到test.data中

NSArray *array = @[@"aa",@"bb",@"cc",@"dd"];

NSString *path = [NSHomeDirectory() stringByAppendingString:@"/Documents/test.data"];

[NSKeyedArchiver archiveRootObject:array toFile:path];

//解档

NSArray *newArray = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

NSLog(@"newA = %@",newArray);


//自定义对象的归档

//核心: 自定义对象实现归档功能,这个类需要遵守NSCoding,并且是实现两个方法

Car *car = [[Car alloc] init];

car.type = @"Audi";

car.speed = 300;

NSString *path = [NSHomeDirectory() stringByAppendingString:@"car.data"];

//归档时候自动调用encodeWithCoder:方法

[NSKeyedArchiver archiveRootObject:car toFile:path];

//解档时候自动调用initWithCoder:方法

Car *newCar = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

NSLog(@"t=%@ s=%f",newCar.type, newCar.speed);


#pragma mark - 分别在归档和解档的时候调用

//Car遵循<NSCoding>协议,实现两个方法

- (void)encodeWithCoder:(NSCoder *)aCoder

{

    //aCoder传入的编码对象

    [aCoder encodeObject:self.type forKey:@"type"];

    [aCoder encodeObject:[NSNumber numberWithDouble:self.speed] forKey:@"speed"];

}

- (id)initWithCoder:(NSCoder *)aDecoder

{

    if(self = [super init])

    {

        self.type = [aDecoder decodeObjectForKey:@"type"];

        self.speed = [[aDecoder decodeObjectForKey:@"speed"] doubleValue];

    }

    return self;

}


//多个类继承时的归档

FlyCar *flyCar = [[FlyCar alloc] init];

flyCar.type = @"Kirui QQ";

flyCar.speed = 88;

flyCar.flySpeed = 888;

flyCar.flyHeight = 8888;


NSString *path = [NSHomeDirectory() stringByAppendingString:@"/Documents/flyCar.data"];

[NSKeyedArchiver archiveRootObject:flyCar toFile:path];


FlyCar *newFlyCar = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

NSLog(@"%@ %f %f %f", newFlyCar.type, newFlyCar.speed, newFlyCar.flyHeight, newFlyCar.flySpeed);


//FlyCar遵循<NSCoding>协议,实现两个方法

-(void)encodeWithCoder:(NSCoder *)aCoder

{

    //子类需要执行父类的编码方法

    [super encodeWithCoder:aCoder];

    [aCoder encodeObject:[NSNumber numberWithDouble:self.flyHeight] forKey:@"flyHeight"];

    [aCoder encodeObject:[NSNumber numberWithDouble:self.flySpeed] forKey:@"flySpeed"];

}

-(id)initWithCoder:(NSCoder *)aDecoder

{

    //子类需要执行父类的解码方法

    if(self = [super initWithCoder:aDecoder])

    {

        self.flyHeight = [[aDecoder decodeObjectForKey:@"flyHeight"] doubleValue];

        self.flySpeed= [[aDecoder decodeObjectForKey:@"flySpeed"] doubleValue];

    }

    return self;

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值