2019-12-01 01:35:36 streamery 阅读数 45

简介

本篇文章使用NSKeyedArchiver和NSKeyedUnarchiver进行iOS的归档解档

  • 归档:即将数据写入文件里。一般我们app的数据都是在内存里,只要app关闭,数据就会丢失。但是将数据保存在文件里,就能将数据保存至本地,不管app关闭还是重启设备,下次启动app的时候都能够读出来
  • 解档:就是将保存的数据从文件中读出来在程序中使用
  • 关于沙盒可以参考:iOS开发关于沙盒

普通数组的归档解档

归档

  • 首先获取文件归档路径
  • 使用方法 archivedDataWithRootObject: requiringSecureCoding: error: 将数据归档到path文件路径里面
  • 方法介绍:
    P1: 要归档的对象
    P2:一个布尔值,指示是否所有编码对象都必须符合NSSecureCoding
    P3:返回的错误
  • 使用方法 writeToFile: atomically: 查看是否归档成功
	//沙盒根目录
    NSString *docPath = NSHomeDirectory();
    //完整的文件路径
    NSString *path = [docPath stringByAppendingPathComponent:@"Documents/numbers.plist"];
    NSArray *numbers = @[@"one",@"two"];
    
    //将数据归档到path文件路径里面
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:numbers requiringSecureCoding:NO error:nil];
    BOOL success = [data writeToFile:path atomically:NO];
    
    if (success) {
        NSLog(@"文件归档成功");
    } else {
        NSLog(@"文件归档失败");
    }

解档

  • 首先获取文件路径
  • 使用方法 dataWithContentsOfFile: 将文件数据化
  • 使用方法 unarchivedObjectOfClass: fromData: error: 转化数据,读取内容
	NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];

    NSString *path = [docPath stringByAppendingPathComponent:@"numbers.plist"];
    NSData *data = [NSData dataWithContentsOfFile:path];
    NSArray *numbers = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:data error:nil];
    NSLog(@"numbers = %@", numbers);

在这里插入图片描述

多个普通对象同时归档解档

上面的例子是将单个的数组或者单个字典归档到一个文件。其实我们也可以将多个数组、字典、字符串、数组等内容归档到同一个文件里面去。

归档

  • 同样先创建归档对象,使用方法 initForWritingWithMutableData: 将归档的数据写入data
  • 使用方法 encodeObject: forKey: 以键值对形式存储归档数据
  • 结束归档
  • 将归档的数据写入文件
	NSDictionary *dic = @{@"one":@"hello",
                          @"two":@1};
    NSInteger age = 10;
    
    NSMutableData *data = [NSMutableData data];
    
    //创建归档对象,归档的数据需要写入data
    NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    
    //键值对形式存储归档数据
    [arch encodeObject:dic forKey:@"Dic"];
    [arch encodeInteger:age forKey:@"Age"];
    
    //结束归档
    [arch finishEncoding];
    NSString *docPath = NSHomeDirectory();
    NSString *manyPath = [docPath stringByAppendingPathComponent:@"Documents/manyData.plist"];
    //将归档的数据写入文件
    [data writeToFile:manyPath atomically:YES];

解档

  • 先创建解档对象
  • 使用方法 initForReadingFromData: error: 将文件数据化
  • 根据键值得到对应数据
	//创建解档对象
    NSString *docPath = NSHomeDirectory();
    NSString *manyPath = [docPath stringByAppendingPathComponent:@"Documents/manyData.plist"];
    NSData *arrayData = [NSData dataWithContentsOfFile:manyPath];
    NSKeyedUnarchiver *unarch = [[NSKeyedUnarchiver alloc] initForReadingFromData:arrayData error:nil];
    //根据键值得到对应数据
    NSDictionary *dic = [unarch decodeObjectForKey:@"Dic"];
    NSInteger age = [unarch decodeIntegerForKey:@"Age"];
    
    //解档结束
    [unarch finishDecoding];
    NSLog(@"%@", dic);
    NSLog(@"%ld", age);

在这里插入图片描述

自定义对象的归档解档

上面的例子,归档的内容都是系统Foundation框架提供的类以及一些基本的数据类型。
Foundation框架提供的类都是实现了NSCoding协议的,所以能够直接进行归档。
如果我们自己自定义了一个类,例如Person类,是无法能够直接将这个类进行归档操作的。
如果想要对自定义的类创建出来的对象进行归档,我们需要先实现NSCoding协议。

Student.h

@interface Student : NSObject
<NSCoding>

@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger grade;

@end

Student.m

#import "Student.h"

@implementation Student

//NSCoding协议方法:将需要归档的属性进行归档
- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeInteger:self.grade forKey:@"grade"];
    [coder encodeObject:self.name forKey:@"name"];
}

//NSCoding协议方法:将需要解档的属性进行解档
- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super init]) {
        self.name = [coder decodeObjectForKey:@"name"];
        self.grade = [coder decodeIntegerForKey:@"grade"];
    }
    return self;
}

归档

此处使用另一种获取目录方法

	//沙盒ducument目录
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    //完整的文件路径
    NSString *path = [docPath stringByAppendingPathComponent:@"student.archiver"];
    
    Student *student = [[Student alloc] init];
    student.name = @"dd";
    student.grade = 22;
    
    //将数据归档到path文件路径里面
    BOOL success = [NSKeyedArchiver archiveRootObject:student toFile:path];
    
    if (success) {
        NSLog(@"归档成功");
    }else {
        NSLog(@"归档失败");
    }

解档

	NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    //完整的文件路径
    NSString *path = [docPath stringByAppendingPathComponent:@"student.archiver"];
    
    Student *student = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    NSLog(@"student's name = %@, student's grade = %lu", student.name, student.grade);

在这里插入图片描述

归档失败

  • 第一种可能:文件夹不存在
    如果文件夹不存在,则创建一个
    //文件夹是否存在
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:dir isDirectory:nil];
    if (!fileExists) {
        NSLog(@"文件夹不存在");
        NSError *error = nil;
        [[NSFileManager defaultManager] createDirectoryAtPath:dir withIntermediateDirectories:YES attributes:nil error:&error];
        if (error) {
            NSLog(@"error == %@", error.description);
        } else {
            NSLog(@"success");
        }
    }
  • 第二种可能:没有写入权限
    有些不熟悉的人可能会遇到这个问题:我在模拟器上归档操作是成功的,可是在真机上运行的时候却归档失败了。到底是什么原因?
    这个就是遇到了写权限的问题了。在模拟器上,因为是写在电脑上面的路径的,所以这个路径我们有写权限。但是真机不一样,真机上我们一般情况下只能操作沙盒路径里面文件夹。无法在其他的地方写文件。
    沙盒根目录也没有写入权限,我们一般在Documents目录写
    //查看是否有写入权限
    if (![[NSFileManager defaultManager] isWritableFileAtPath:dir]) {
        NSLog(@"目录无写入权限");
    }

文章参考文献:【iOS】数据持久化:使用NSKeyedArchiver进行数据归档

2017-01-18 00:47:01 coderMy 阅读数 455

在开发中 , 通常会运用到一些全局的单例 , 保存用户的基本信息或者一些基本状态 . 这个时候可能会运用到单例来保存信息 , 保证全局获取到的都是最新的相同的信息. 并且,一般全局单例的属性较多 , 比如包括了用户的姓名,手机号,性别,城市,年龄等等众多信息.如果对该单例的各项属性进行归档, 那么得让此单例遵循协议,并实现 - (id)initWithCoder:(NSCoder *)decoder- (void)encodeWithCoder:(NSCoder *)encoder 方法.


首先 , 定义一个单例对象

+ (instancetype)shareInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        account = [[JYAccount alloc]init];
    });
    return account;
}

假如该单例有如下属性

@property (nonatomic, strong) NSNumber *sex;                 //性别
@property (nonatomic, strong) NSNumber *registerTime;        //注册时间
@property (nonatomic , copy) NSString *level;
@property (nonatomic , copy) NSString *mobile;               //手机号
@property (nonatomic , copy) NSString *nickName;             //昵称
@property (nonatomic , copy) NSString *portrait;             //头像图片路径
@property (nonatomic , copy) NSString *status;
@property (nonatomic , copy) NSString *tokenId;              //唯一标识
@property (nonatomic , copy) NSString *userName;             //用户名

归档


- (void)encodeWithCoder:(NSCoder *)encoder

此方法通俗一点讲 , 就是告诉系统该如何存属性 , 如果用通常的方法做 , 实现 - (void)encodeWithCoder:(NSCoder *)encoder方法如下

- (void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.name forKey:@"sex"];
    [encoder encodeObject:self.password forKey:@"registerTime"];
    [encoder encodeObject:self.photo forKey:@"level"];
    [encoder encodeObject:self.roleId forKey:@"mobile"];
    [encoder encodeObject:self.sex forKey:@"nickName"];
    [encoder encodeObject:self.tokenid forKey:@"portrait"];
    [encoder encodeObject:self.userId forKey:@"status"];
    [encoder encodeObject:self.phoneNum forKey:@"tokenId"];
    [encoder encodeObject:self.phoneNum forKey:@"userName"];
}

如果用runtime快速归档

- (void)encodeWithCoder:(NSCoder *)encoder
{
    unsigned int count;
    Ivar *ivar = class_copyIvarList([JYAccount class], &count); //获取属性列表
    for (NSInteger index = 0; index <count; index++) { //遍历属性列表获取每个属性 , 并从中取值
        Ivar iv = ivar[index];
        const char *name = ivar_getName(iv);
        NSString *strName = [NSString stringWithUTF8String:name];

        id value = [self valueForKey:strName];
        [encoder encodeObject:value forKey:strName];
    }
    free(ivar); //释放
}

解档


- (id)initWithCoder:(NSCoder *)decoder

 - (id)initWithCoder:(NSCoder *)decoder
{
    if (self = [super init]) {
        self.name = [decoder decodeObjectForKey:@"sex"];
        self.password = [decoder decodeObjectForKey:@"registerTime"];
        self.photo = [decoder decodeObjectForKey:@"level"];
        self.roleId = [decoder decodeObjectForKey:@"mobile"];
        self.sex = [decoder decodeObjectForKey:@"nickName"];
        self.tokenid = [decoder decodeObjectForKey:@"portrait"];
        self.userId = [decoder decodeObjectForKey:@"status"];
        self.phoneNum = [decoder decodeObjectForKey:@"tokenId"];
        self.phoneNum = [decoder decodeObjectForKey:@"userName"];
    }
    return self;
}

如果用tuntime快速解档

- (id)initWithCoder:(NSCoder *)decoder
{
    if (self = [super init]) {
        unsigned int count = 0;
        //获取类中所有成员变量名
        Ivar *ivar = class_copyIvarList([JYAccount class], &count);  //获取属性列表
        for (NSInteger index = 0; index<count; index++) {  //获取每个属性,并对其赋值
            Ivar iva = ivar[index];
            const char *name = ivar_getName(iva);
            NSString *strName = [NSString stringWithUTF8String:name];
            id value = [decoder decodeObjectForKey:strName];
            [self setValue:value forKey:strName];
        }
        free(ivar); //释放
    }
    return self;
}

当你的单例中,有上十个属性,甚至几十个属性时 , 灵活运用runtime进行归档 , 能为你省下不少的代码 ,看着也不至于很Low …

2017-03-01 13:57:35 Nvermore_ 阅读数 308

Runtime - 多属性快速归档解档

对象归档,就是把内存中对象存储到本地。(归档的实质就是将OC对象拆分为键值对的字典,然后变成二进制存入磁盘)

对象解档,就是把本地的对象读取到内存。

常规的归解档:

创建一个Model类:Student(遵循NSCoding协议,实现归解档协议方法)

//  Student.h
#import <Foundation/Foundation.h>

@interface Student : NSObject<NSCoding>

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSUInteger age;
@property (nonatomic, copy) NSString *sex;

@end

//  Student.m
#import "Student.h"

@implementation Student
//告诉系统归档哪些属性
- (void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInteger:_age forKey:@"age"];
    [aCoder encodeObject:_sex forKey:@"sex"];
}

//解档的属性
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        _name = [aDecoder decodeObjectForKey:@"name"];
        _age = [aDecoder decodeIntegerForKey:@"age"];
        _sex = [aDecoder decodeObjectForKey:@"sex"];
    }
    return self;
}


在需要归解档的地方写上归解档方法并调用

//归档方法
- (void)save{
    //创建一个用于归档的对象并赋值
    Student *s = [[Student alloc]init];
    s.name = @"haha";
    s.age = 18;
    s.sex = @"boy";
    
    //获取沙沙盒路径
    NSString *temPath = NSTemporaryDirectory();
    //创建文件路径  stringByAppendingPathComponent 不用再加“/”
    NSString *filePath = [temPath stringByAppendingPathComponent:@"student.wsy"];
    NSLog(@"filePath==%@",filePath);
    
    //归档    file:绝对路径  需要遵守NSCoding协议
    [NSKeyedArchiver archiveRootObject:s toFile:filePath];
}

//解档方法
- (void)read{
    //获取沙沙盒路径
    NSString *temPath = NSTemporaryDirectory();
    //获取要解档文件路径
    NSString *filePath = [temPath stringByAppendingPathComponent:@"student.wsy"];
    
    Student *s = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
    NSLog(@"名字:%@ 年龄:%zi 性别:%@",s.name, s.age, s.sex);
}

  调用归档方法结果:(创建了文件,对象应该也存进去了,一会解档验证)



调用解档方法结果:(取出了对象,证明归解档成功)



那么我们就可以思考一下:如果对象属性特别多的时候,在协议方法里实现属性encode和decode就会比较麻烦,需要写好多encode 和 decode

而如果利用循环的话,我们需要知道三点:属性个数、各属性名称、各具体属性

//告诉系统归档哪些属性(解档同理)
- (void)encodeWithCoder:(NSCoder *)aCoder{
    // 伪代码  1.遍历属性个数  2.获取属性名称
    for (int i = 0; i < 属性个数 ; i++) {
        [[aCoder encodeObject:属性 forKey:属性名称];]
    }
    
}

下面就可以用到Runtime了,使用Runtime需要导入#import <objc/runtime.h>

我们可以利用 Ivar  -  成员属性

//方法:class_copyIvarList(<#__unsafe_unretained Class cls#>, <#unsigned int *outCount#>)
    //两个参数:
    //__unsafe_unretained Class cls class类型
    //unsigned int *outCount 无符号自增整型指针
    //返回值为Ivar * 类型 是个指向ivar列表地址的指针 (可以通过KVC进行修改了,小心私有API)
//示例
    unsigned int count = 0;
    Ivar * ivars = class_copyIvarList(NSClassFromString(@"Student"), &count);
    //count实质就是属性的个数(甚至放在.m里的私有属性一样能够统计进去)
    NSLog(@"count==%u",count);
    
    //ivars 是属性列表指针 通过++可以往下逐一获取到ivar,当然注意边界,越界不会崩溃,越界之后如果拿到垃圾信息就会报错
    Ivar ivar = ivars[0];
    //通过ivar_getName 可以获取到名字(返回值为c语言字符串)
    const char *name = ivar_getName(ivar);
    NSLog(@"%s",name);

打印结果:(我的Student里确实有三个属性,且.m里米有私有属性   第0个位置的确实是name属性)



OK,那么我们就可以愉快的使用了,所以model类的.m文件就变成了这样:

//  Student.m
#import "Student.h"
#import <objc/runtime.h>

@implementation Student
//告诉系统归档哪些属性
- (void)encodeWithCoder:(NSCoder *)aCoder{
    //属性个数
    unsigned int count = 0;
    Ivar * ivars = class_copyIvarList([Student class], &count);
    
    for (int i = 0; i < count; i++) {
        //拿到属性
        Ivar ivar = ivars[i];
        //拿到名称
        const char *name = ivar_getName(ivar);
        //转换成OC字符串
        NSString *key = [NSString stringWithUTF8String:name];
        [aCoder encodeObject:[self valueForKey:key] forKey:key];
    }
    //C语言里由Creat Copy创造的指针需要手动释放 ARC只管OC对象
    free(ivars);
    
}

//解档的属性
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        //属性个数
        unsigned int count = 0;
        Ivar * ivars = class_copyIvarList([Student class], &count);
        
        for (int i = 0; i < count; i++) {
            //拿到属性
            Ivar ivar = ivars[i];
            //拿到名称
            const char *name = ivar_getName(ivar);
            //转换成OC字符串
            NSString *key = [NSString stringWithUTF8String:name];
            //解档
            id value = [aDecoder decodeObjectForKey:key];
            //设置到属性上
            [self setValue:value forKey:key];
        }
        //C语言里由Creat Copy创造的指针需要手动释放 ARC只管OC对象
        free(ivars);
    }
    return self;
}

OK,这里写完就可以愉快的进行归解档了,属性再多也不怕了!











2019-01-19 15:03:22 zjpjay 阅读数 375

前言

在之前的文章什么是序列化?序列化的作用是什么?iOS中怎么实现序列化?中我们用普通方法实现了对象的序列化操作,也就是归档和解档。

对遵循了NSCoding协议的iOS对象进行归档和解档是我们经常用到的一种数据持久化方式。但是如果对象的属性太多了我们还是对每个属性都实现一遍encodeObject:forKey:decodeObjectForKey:方法,这样写的代码量太多了,会显得很繁琐,今天就教大家用一个简单的方法来实现。

1.创建遵循NSCoding协议的Person对象


#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject<NSCoding>

@property (copy,   nonatomic) NSString *name;
@property (copy,   nonatomic) NSString *sex;
@property (assign, nonatomic) NSInteger age;
@property (assign, nonatomic) NSInteger height;

@end

NS_ASSUME_NONNULL_END

2.Person.m 代码实现归档和解档

  • runtime归档
- (void)encodeWithCoder:(NSCoder *)coder {
		//告诉系统归档的属性是哪些
	unsigned int count = 0;//表示对象的属性个数
	Ivar *ivars = class_copyIvarList([Person class], &count);
	for (int i = 0; i < count; i++) {
			//拿到Ivar
		Ivar ivar = ivars[i];
		const char *name = ivar_getName(ivar);//获取到属性的C字符串名称
		NSString *key = [NSString stringWithUTF8String:name];//转成对应的OC名称
		//归档 -- 利用KVC
		[coder encodeObject:[self valueForKey:key] forKey:key];
	}
	free(ivars);
		//在OC中使用了Copy、Creat、New类型的函数,需要释放指针!!(注:ARC管不了C函数)
}
  • runtime解档
- (instancetype)initWithCoder:(NSCoder *)coder {
	self = [super init];
	if (self) {
			//解档
		unsigned int count = 0;
		Ivar *ivars = class_copyIvarList([Person class], &count);
		for (int i = 0; i<count; i++) {
				//拿到Ivar
			Ivar ivar = ivars[i];
			const char *name = ivar_getName(ivar);
			NSString *key = [NSString stringWithUTF8String:name];
				//解档
			id value = [coder decodeObjectForKey:key];
				// 利用KVC赋值
			[self setValue:value forKey:key];
		}
		free(ivars);
	}
	return self;
}


使用runtime的好处不言而喻,无论对象有多少属性都可以通过这个for循环搞定,非常厉害,非常方便。不知道你学会了吗?

2015-09-24 11:38:47 u012701023 阅读数 2270

归档解档是OC 中很重要的知识点

弥补了NSUserDefaults 的不足 可以存储自定义的对象

我们可以存储多个对象 需要一个数组接受即可

#import <Foundation/Foundation.h>

@interface User : NSObject<NSCoding>


@property (nonatomic, copy)NSString *name;

@property (nonatomic, copy)NSString *passwd;

+ (User *)userWithName:(NSString *)name password:(NSString *)
password;

@end

#import "User.h"

@implementation User

 + (User *)userWithName:(NSString *)name password:(NSString *)password
{
    User *user = [[User alloc]init];
    user.name = name;
    user.passwd = password;
    
    return user;
}

//归档调用方法
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.passwd forKey:@"passwd"];
    
}


//接档调用方法
//取值
- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {
     self.name = [aDecoder decodeObjectForKey:@"name"];
     self.passwd = [aDecoder decodeObjectForKey:@"passwd"];
    }
    return self;
}
@end

#import "ViewController.h"
#import "User.h"
#import "UserDefaultKeysConfig.h"


@interface ViewController ()
#pragma mark - 属性方法定义
@property (weak, nonatomic) IBOutlet UITextField *usernameTextField;
@property (weak, nonatomic) IBOutlet UITextField *passwdTextField;

- (IBAction)loginBtn:(id)sender;
- (IBAction)exitBtn:(id)sender;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
//    self.usernameTextField.text = @"angel";
//    self.passwdTextField.text = @"123456";
//
//    self.usernameTextField.text = [[NSUserDefaults standardUserDefaults]objectForKey:kUserNameKey];
//    self.passwdTextField.text = [[NSUserDefaults standardUserDefaults]objectForKey:kUserPwdKey];
    // Do any additional setup after loading the view, typically from a nib.
    
    User *user = [self userFromArachiver];
    self.usernameTextField.text = user.name;
    self.passwdTextField.text = user.passwd;
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    

    // Dispose of any resources that can be recreated.
}


#pragma mark - 存储信息
//点击登陆按钮 将信息存储到沙盒
- (IBAction)loginBtn:(id)sender {
    
//    [[NSUserDefaults standardUserDefaults]setObject:self.usernameTextField.text forKey:kUserNameKey];
//    [[NSUserDefaults standardUserDefaults]setObject:self.passwdTextField.text forKey:kUserPwdKey];
//    
//    //同步写入文件
//    [[NSUserDefaults standardUserDefaults]synchronize];
    
    //1.封装数据模型 用提供的类方法快速创建一个类
    User *user = [User userWithName:self.usernameTextField.text password:self.passwdTextField.text];
    [self saveUserObjectWithUser:user];
    
}

#pragma mark - 解归档

- (User *)userFromArachiver
{
    //1.首先判断文件是否存在
    if(![[NSFileManager defaultManager] fileExistsAtPath:[[self class]path]])
    {
        return nil;
    }
    
    //2.读取data对象
    NSData *data = [NSData dataWithContentsOfFile:[[self class]path]];
    
    //3.穿件解归档对象
    NSKeyedUnarchiver *unarchive = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
    
    //4.解档 创建接受对象
    User * user =  [unarchive decodeObjectForKey:@"user"];
    
    //5.完成解档
    [unarchive finishDecoding];
    
    NSLog(@"%@",user.name);
    NSLog(@"%@---",user.passwd);
    
    return user;
    
}



#pragma mark - 归档
/**
 *  归档
 *
 *  @param user <#user description#>
 */
- (void)saveUserObjectWithUser:(User *)user
{
    //我们要将自定义对象转化为二进制流 并写入沙盒 我们要进行以下操作
    //1.先创建一个NSMutableData对象
    NSMutableData *data = [NSMutableData data];
    //2.创建一个归档对象
    NSKeyedArchiver *archive = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
    
    //3.归档
    [archive encodeObject:user forKey:@"user"];
    
    //4.完成归档
    [archive finishEncoding];
    
    //5.写入文件
    [data writeToFile: [[self class] path] atomically:YES];
}

//怎样调用一个类方法
+ (NSString *)path
{

    NSString *chachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask , YES)lastObject];
    
    return [chachePath stringByAppendingPathComponent:@"user"];
}



#pragma mark - 退出
- (IBAction)exitBtn:(id)sender {
    
    
    [[NSUserDefaults standardUserDefaults]removeObjectForKey:kUserNameKey];
    [[NSUserDefaults standardUserDefaults]removeObjectForKey:kUserPwdKey];
    [[NSUserDefaults standardUserDefaults]synchronize];
    
    self.usernameTextField.text = @"";
    self.passwdTextField.text = @"";
}
@end


ios 归档接档

阅读数 383

iOS 完全深复制

阅读数 41

没有更多推荐了,返回首页