美文网首页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

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