NSCoding的简单使用

NSCoding是一个协议,如果实现这个协议,就可以将这个类转换成NSData,并互相转换

使用场景1,NSUserDefaults存储数据时,需要转成NSData

使用场景2,因为NSData提供了一个方法来存储数据

NSCorder类是一个抽象类,用来被其他的类继承。

NSCorder定义了一些接口,使数据从内存到其他格式的转换。

NSKeyedArchiver和NSKeyedUnarchiver

NSKeyedArchiver将自定义类转化成NSData实例,类里面的每一个值对应一个key

NSKeyedUnarchiver将NSData实例根据key的值还原成自定义的类。

NSCoding和NSSecureCoding(iOS6以后)

NSCoding安全性不高,存储到rom中会被篡改

NSSecureCoding安全的,会进行类型检查,类型不匹配,就抛出异常。

具体代码实现地址:https://gitee.com/xgkp/NSSecureCodingDemoo.git

说明:
创建一个工程名字叫NSSecureCodingDemoo

创建一个类叫MyDog

MyDog.h中代码,注意这里的

#import 

NS_ASSUME_NONNULL_BEGIN

@interface MyDog : NSObject

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

@end

NS_ASSUME_NONNULL_END

在MyDog.h中的代码

#import "MyDog.h"

@implementation MyDog

+(BOOL)supportsSecureCoding
{
    return YES;
}

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

-(void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:_name forKey:@"name"];
    [coder encodeInteger:_age forKey:@"age"];
}


@end

viewcontroller中的代码,注意这里的实现是在iOS13之后,demo的版本是在iOS13及以后的实现,部分方法如果在iOS12以前实现有所不同


#import "ViewController.h"
#import "MyDog.h"

@interface ViewController ()
@property (nonatomic,strong) NSData *archiveData;
@end

@implementation ViewController

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

- (IBAction)dogToData:(id)sender {
//    myDog to nsdata
    NSData * data = [NSMutableData data];

    MyDog * dog = [[MyDog alloc] init];
    dog.name = @"泰迪";
    dog.age= 2;
    NSError *error = nil;

    data = [NSKeyedArchiver archivedDataWithRootObject:dog requiringSecureCoding:YES error:&error];
    
    if (data == nil || error) {
        NSLog(@"%@",error);
        return;
    }
    _archiveData = [data copy];
    
}

- (IBAction)dataToDog:(id)sender {
    
//    data -> mydog
    NSError * error = nil;
    MyDog * dog = [NSKeyedUnarchiver unarchivedObjectOfClass:[MyDog class] fromData:_archiveData error:&error];
    NSLog(@"%@",dog.name);
    NSLog(@"%ld",dog.age);
}





@end


在实际开发中可以直接使用category来实现NSKeyedUnarchiver+ConvertNSData

//
//  NSKeyedUnarchiver+ConvertNSData.h
//  NSSecureCodingDemoo
//
//  Created by hpkj on 2020/1/19.
//


#import 

NS_ASSUME_NONNULL_BEGIN

@interface NSKeyedUnarchiver (ConvertNSData)
+(id)customInstanceFromData:(NSData *)data ForClass:(Class)classType;
@end

NS_ASSUME_NONNULL_END




//
//  NSKeyedUnarchiver+ConvertNSData.m
//  NSSecureCodingDemoo
//
//  Created by hpkj on 2020/1/19.
//

#import "NSKeyedUnarchiver+ConvertNSData.h"



@implementation NSKeyedUnarchiver (ConvertNSData)
+(id)customInstanceFromData:(NSData *)data ForClass:(Class)classType
{
    NSError * error = nil;
     return  [NSKeyedUnarchiver unarchivedObjectOfClass:[classType class] fromData:data error:&error];
}

@end


Category的NSKeyedArchiver+ConvertNSData.h实现

//
//  NSKeyedArchiver+ConvertNSData.h
//  NSSecureCodingDemoo
//
//  Created by hpkj on 2020/1/19.
//

#import 

NS_ASSUME_NONNULL_BEGIN

@interface NSKeyedArchiver (ConvertNSData)
+(NSData *)dataWithCustomClass:(id)customClass;

@end

NS_ASSUME_NONNULL_END


//
//  NSKeyedArchiver+ConvertNSData.m
//  NSSecureCodingDemoo
//
//  Created by hpkj on 2020/1/19.
//

#import "NSKeyedArchiver+ConvertNSData.h"



@implementation NSKeyedArchiver (ConvertNSData)
+(NSData *)dataWithCustomClass:(id)customClass
{
    NSMutableData * data = [NSMutableData data];
    NSError *error = nil;
    data = [NSKeyedArchiver archivedDataWithRootObject:customClass requiringSecureCoding:YES error:&error];
    return [data copy];
}




@end

总结:如果希望自定义类或者model数据类能够被存储到缓存中,可以将类的实现中加上NSSecureCoding协议的实现

你可能感兴趣的:(NSCoding的简单使用)