美文网首页iOS底层探究
NSCoding对象存储(注意:以后使用NSSecureCodi

NSCoding对象存储(注意:以后使用NSSecureCodi

作者: 皮蛋豆腐酱油 | 来源:发表于2018-09-29 14:16 被阅读0次

1. NSCoding是一个协议,遵守NSCoding协议的类,可以实现这个类到NSData的互相转换

2. 使用场景

  • NSUserDefaults 将自定义的类转换成NSData实例,然后存储到偏好存储中。
  • 文件存储 :NSData类提供了一个方法,可以直接将NSData实例存储到文件中

3. 相关知识介绍

  • NSCoder类是一个抽象类,用来被其他的类继承
  • NSKeyedArchiver 和 NSKeyedUnarchiver,NSKeyedArchiver将自定义的类转换成NSData实例,类里面每一个值对应一个Key;NSKeyedUnarchiver将NSData实例根据key值还原成自定义的类。
  • NSCoding 和 NSSecureCoding,NSCoding安全性不高,所以iOS6的时候,苹果引入了NSSecureCoding协议,加强安全性。
  • NSSecureCoding:存取方法一定要使用NSSecureCoding的。

4. 代码实现NSSecureCoding

//
//  MyDog.h
//  NSSecureCoding

#import <Foundation/Foundation.h>

@interface MyDog : NSObject<NSSecureCoding>
@property(nonatomic, strong) NSString *name;
@property(nonatomic, assign) NSInteger age;
@end
//
//  MyDog.m
//  NSSecureCoding

#import "MyDog.h"

@implementation MyDog

+ (BOOL)supportsSecureCoding {
    return YES; //支持加密编码
}

//解码方法
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        if (aDecoder) {
            _name = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"name"];
            _age = [aDecoder decodeIntegerForKey:@"age"];
        }
    }
    return self;
}

//编码方法
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInteger:_age forKey:@"age"];
}
@end
//
//  ViewController.m
//  NSSecureCoding

#import "ViewController.h"
#import "MyDog.h"
@interface ViewController ()

@property(nonatomic, strong)NSData *archivedData;
- (IBAction)archiveObject:(id)sender;
- (IBAction)UnArchiveObject:(id)sender;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


- (IBAction)archiveObject:(id)sender {
    //MyDog -> NSData
    NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
    //设置安全加密
    [archiver setRequiresSecureCoding:YES];
    //开始编码
    MyDog *dog = [[MyDog alloc]init];
    dog.name = @"泰迪";
    dog.age = 2;
    
    [archiver encodeObject:dog forKey:NSKeyedArchiveRootObjectKey];
    //结束编码
    [archiver finishEncoding];
    
    _archivedData = [data copy];
}

- (IBAction)UnArchiveObject:(id)sender {
    //NSData -> MyDog
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:_archivedData];
    [unarchiver setRequiresSecureCoding:YES];
    MyDog *dog = [unarchiver decodeObjectOfClass:[MyDog class] forKey:NSKeyedArchiveRootObjectKey];
    NSLog(@"%@ %ld",dog.name,(long)dog.age);
}
@end

5. 增加分类,更加方便的解码编码

增加分类时New File -> Objective-C File
File Type选择分类Category
Class 解码的选择NSKeyedUnarchiver 编码的选择NSKeyedArchiver

//
//  NSKeyedArchiver+ConvertNSData.h
//  NSSecureCoding

#import <Foundation/Foundation.h>

@interface NSKeyedArchiver (ConvertNSData)

+ (NSData *)dataWithCustomClass:(id<NSSecureCoding>)customClassObject;

@end
//
//  NSKeyedArchiver+ConvertNSData.m
//  NSSecureCoding

#import "NSKeyedArchiver+ConvertNSData.h"

@implementation NSKeyedArchiver (ConvertNSData)

+ (NSData *)dataWithCustomClass:(id<NSSecureCoding>)customClassObject {
    NSMutableData *data = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
    [archiver setRequiresSecureCoding:YES];
    [archiver encodeObject:customClassObject forKey:NSKeyedArchiveRootObjectKey];
    [archiver finishEncoding];
    return data;
}

@end
//
//  NSKeyedUnarchiver+ConvertNSData.h
//  NSSecureCoding

#import <Foundation/Foundation.h>

@interface NSKeyedUnarchiver (ConvertNSData)

+ (id<NSSecureCoding>)customInstanceFromData:(NSData *)data ForClass:(Class)classType;

@end
//
//  NSKeyedUnarchiver+ConvertNSData.m
//  NSSecureCoding

#import "NSKeyedUnarchiver+ConvertNSData.h"

@implementation NSKeyedUnarchiver (ConvertNSData)

+ (id<NSSecureCoding>)customInstanceFromData:(NSData *)data ForClass:(Class)classType {
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
    [unarchiver setRequiresSecureCoding:YES];
    
    return [unarchiver decodeObjectOfClass:[classType class] forKey:NSKeyedArchiveRootObjectKey];
}

@end
//
//  MyDog.h
//  NSSecureCoding

#import <Foundation/Foundation.h>

@interface MyDog : NSObject<NSSecureCoding>
@property(nonatomic, strong) NSString *name;
@property(nonatomic, assign) NSInteger age;
@end
//
//  MyDog.m
//  NSSecureCoding

#import "MyDog.h"

@implementation MyDog

+ (BOOL)supportsSecureCoding {
    return YES; //支持加密编码
}

//解码方法
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        if (aDecoder) {
            _name = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"name"];
            _age = [aDecoder decodeIntegerForKey:@"age"];
        }
    }
    return self;
}

//编码方法
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInteger:_age forKey:@"age"];
}
@end
//
//  ViewController.m
//  NSSecureCoding

#import "ViewController.h"
#import "MyDog.h"
#import "NSKeyedArchiver+ConvertNSData.h"
#import "NSKeyedUnarchiver+ConvertNSData.h"
@interface ViewController ()

@property(nonatomic, strong)NSData *archivedData;
- (IBAction)archiveObject:(id)sender;
- (IBAction)UnArchiveObject:(id)sender;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


- (IBAction)archiveObject:(id)sender {
    //MyDog -> NSData
    //开始编码
    MyDog *dog = [[MyDog alloc]init];
    dog.name = @"泰迪";
    dog.age = 2;
    
    _archivedData = [NSKeyedArchiver dataWithCustomClass:dog];
}

- (IBAction)UnArchiveObject:(id)sender {
    //NSData -> MyDog
    MyDog *dog = (MyDog *)[NSKeyedUnarchiver customInstanceFromData:_archivedData ForClass:[MyDog class]];
    NSLog(@"%@ %ld",dog.name,(long)dog.age);
}
@end

相关文章

  • NSCoding对象存储(注意:以后使用NSSecureCodi

    1. NSCoding是一个协议,遵守NSCoding协议的类,可以实现这个类到NSData的互相转换 2. 使用...

  • NSCoding

    使用场景: 将对象存储成文件,当需要的时候随时可以调用 要求: 遵守NSCoding协议 NSCoding相关的类...

  • iOS 归档

    写入数据 读取数据 注意:如果使用归档 该对象必须遵守NSCoding 协议 编码协议 实现 encodeWith...

  • OC基本常识

    判断对象类型 动态跳转页面 数据存储 下面主要讲的是存储对象的问题;如果一个对象要存储,就要进行 nscoding...

  • iOS的encodeWithCoder

    待填充 encodeWithCoder 将对象进行归档存储时,需要遵循NSCoding协议,对象必须实现encod...

  • 归档NSSecureCoding的使用

    NSCoding是一种非安全的编解码方式,使用NSKeyedArchiver归档自定义类对象做持久化存储。由于未做...

  • iOS NSCoding 与 NSSecureCoding

    NSCoding 简介NSCoding是把数据存储在iOS和Mac OS上的一种极其简单和方便的方式,它把模型对象...

  • iOS_NSCoding与NSSecureCoding

    NSCoding NSCoding是把数据存储在iOS和Mac OS上的一种极其简单和方便的方式,它把模型对象直接...

  • iOS NSCoding / NSKeyed​Archiver

    一:要想使对象可以直接存储,首先要遵循NSCoding协议 @interface Person : NSObjec...

  • iOS 使用RGArchiver存储OC对象

    iOS自定义对象存储,必须继承NSCoding协议,实现对应的- (void)encodeWithCoder:(N...

网友评论

    本文标题:NSCoding对象存储(注意:以后使用NSSecureCodi

    本文链接:https://www.haomeiwen.com/subject/dammoftx.html