对象归档与KVC KVO
Posted 亚洲小炫风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对象归档与KVC KVO相关的知识,希望对你有一定的参考价值。
对象归档是一个过程,即某种格式来保存一个或者多个对象,以便以后还原这些对象
在其他语言中,对象归档也叫对象序列化
对象归档包括两个过程
--将对象状态写入文件
--从文件中写入对象
自定义对象只有实现NSCoding协议(ios 13需要支持NSSecureCoding)才能支持归档操作
-initWithCoder:从文件中还原对象(解档)
-encodeWithCoder: 将对象归档
User.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface User : NSObject<NSSecureCoding>
@property(nonatomic,copy) NSString *name;
@property(nonatomic,assign) int age;
@end
NS_ASSUME_NONNULL_END
User.m
#import "User.h"
@implementation User
//解档
- (instancetype)initWithCoder:(NSCoder *)coder
self = [super init];
if (self)
self.name =[coder decodeObjectForKey:@"name"];
self.age = [coder decodeIntForKey:@"age"];
return self;
+ (BOOL)supportsSecureCoding
return true;
- (void)encodeWithCoder:(NSCoder *)coder
[coder encodeObject:self.name forKey:@"name"];
[coder encodeInt:_age forKey:@"age"];
- (NSString *)description
return [NSString stringWithFormat:@"name:%@ age:%d", _name,_age];
@end
User *u=[[User alloc] init];
u.name=@"张三";
u.age=14;
NSError *error;
NSData *data=[NSKeyedArchiver archivedDataWithRootObject:u requiringSecureCoding:YES error:&error];
if(error!=nil)
NSLog(@"======>归档错误:%@",error);
return;
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"test.archiver"];
//创建文件
[[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
//写入
[data writeToFile:path atomically:YES];
//解档
NSData *data2=[NSData dataWithContentsOfFile:path];
error=nil;
User *unarchiverUser=(User *)[NSKeyedUnarchiver unarchivedObjectOfClass:[User class] fromData:data2 error:&error];
if(error!=nil)
NSLog(@"======>解档错误:%@",error);
NSLog(@"=====>unarchiverUser:%@",unarchiverUser);
将多个对象归档在同一个文件中
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"test22.archiver"];
//将多个对象归档在同一个文件中
User *user=[[User alloc] init];
user.name=@"张三";
user.age=24;
User *user2=[User new];
user2.name=@"李四";
user2.age=25;
NSKeyedArchiver *archiver=[[NSKeyedArchiver alloc] initRequiringSecureCoding:NO];
[archiver encodeObject:user forKey:@"user"];
[archiver encodeObject:user2 forKey:@"user2"];
[archiver.encodedData writeToFile:path atomically:YES];
[archiver finishEncoding];
NSData *data=[NSData dataWithContentsOfFile:path];
NSKeyedUnarchiver *unarchiver=[[NSKeyedUnarchiver alloc] initForReadingFromData:data error:nil];
[unarchiver setRequiresSecureCoding:NO];
User *unarchiverUser=[unarchiver decodeObjectForKey:@"user"];
User *unarchiverUser2=[unarchiver decodeObjectForKey:@"user2"];
NSLog(@"======>test unarchiverUser:%@",unarchiverUser);
NSLog(@"======>test unarchiverUser2:%@",unarchiverUser2);
kvc( Key-value coding) 键值对编码 本质对象就是字典 ,类似java的反射
user.h
#import <Foundation/Foundation.h>
#import "Teacher.h"
NS_ASSUME_NONNULL_BEGIN
@interface User : NSObject
@property(nonatomic,copy) NSString *name;
@property(nonatomic,assign) int age;
@property(nonatomic,strong) Teacher *teacher;
@end
NS_ASSUME_NONNULL_END
User *u=[[User alloc] init];
u.name=@"李四";
[u setValue:@"张三" forKey:@"name"];
NSLog(@"=======>u:%@",u);//=======>u:<User: 0x600003ace8e0>
Teacher *t=[Teacher new];
t.name=@"李明老师";
[u setValue:t forKey:@"teacher"];
NSLog(@"=======>u.teacher:%@",u.teacher.name);//=======>u.teacher:李明老师
//forpath 可以指定嵌套的属性的值
[u setValue:@"张明老师" forKeyPath:@"teacher.name"];
NSLog(@"=======>u.teacher:%@",u.teacher.name);//=======>u.teacher:张明老师
NSString *name= [u valueForKey:@"name"];
NSLog(@"=======>name:%@",name);// =======>name:张三
NSString *teacherName=[u valueForKeyPath:@"teacher.name"];
NSLog(@"=======>teacherName:%@",teacherName);// =======>u.teacher:张明老师
kvo 是 key value obsever 监视对象改变
实例:
User.h
#import <Foundation/Foundation.h>
#import "Watcher.h"
NS_ASSUME_NONNULL_BEGIN
@interface User : NSObject
@property(nonatomic,strong) NSString *name;
@property(nonatomic,strong) Watcher *watcher;
@end
NS_ASSUME_NONNULL_END
User.m
#import "User.h"
@implementation User
- (void)setWatcher:(Watcher *)watcher
_watcher=watcher;
[self addObserver:self.watcher forKeyPath:@"name" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:@"address changed"];
- (void)dealloc
//销毁的时候移除观察者
if(_watcher!=nil)
[self removeObserver:self.watcher forKeyPath:@"name"];
@end
Watcher.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Watcher : NSObject
@end
NS_ASSUME_NONNULL_END
Watcher.m
#import "Watcher.h"
@implementation Watcher
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
NSLog(@"========>数据发生改变了 keyPath:%@",keyPath);//========>数据发生改变了 keyPath:name
NSLog(@"========>数据发生改变了 change old:%@",change[@"old"]);//========>数据发生改变了 change old:张三
NSLog(@"========>数据发生改变了 change new:%@",change[@"new"]);//========>数据发生改变了 change new:李四
NSLog(@"========>数据发生改变了 change new valueForKeyPath:%@",[object valueForKeyPath:keyPath]);//========>数据发生改变了 change new valueForKeyPath:李四
NSLog(@"========>数据发生改变了 change context:%@",context);//========>数据发生改变了 change context:address changed
@end
总结:1.观察一个对象 有观察者Watcher 被观察者User
2.被观察者属性改变可以通过注册一个对象 到具体的属性上
2. 观察者遇到被观察者发生改变 观察者会回调 observeValueForKeyPath 系统方法
以上是关于对象归档与KVC KVO的主要内容,如果未能解决你的问题,请参考以下文章