NSCoding
是一种非安全的编解码方式,使用NSKeyedArchiver
归档自定义类对象做持久化存储。由于未做数据校验,可通过篡改本地存储的信息进行攻击。从IOS 6.0之后引入了NSSecureCoding
来保证数据安全。
NSSecureCoding
协议继承自NSCoding
,有着比NSCoding
更加安全的编码和解码。
在iOS 12.0以后,仅保留了两个方法
/**
Initializes the receiver for encoding an archive, optionally disabling secure coding.
If \c NSSecureCoding cannot be used, \c requiresSecureCoding may be turned off here; for improved security, however, \c requiresSecureCoding should be left enabled whenever possible. \c requiresSecureCoding ensures that all encoded objects conform to \c NSSecureCoding, preventing the possibility of encoding objects which cannot be decoded later.
To produce archives whose structure matches those previously encoded using \c +archivedRootDataWithObject, encode the top-level object in your archive for the \c NSKeyedArchiveRootObjectKey.
*/
- (instancetype)initRequiringSecureCoding:(BOOL)requiresSecureCoding API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
/**
Returns an \c NSData object containing the encoded form of the object graph whose root object is given, optionally disabling secure coding.
If \c NSSecureCoding cannot be used, \c requiresSecureCoding may be turned off here; for improved security, however, \c requiresSecureCoding should be left enabled whenever possible. \c requiresSecureCoding ensures that all encoded objects conform to \c NSSecureCoding, preventing the possibility of encoding objects which cannot be decoded later.
If the object graph cannot be encoded, returns \c nil and sets the \c error out parameter.
*/
+ (nullable NSData *)archivedDataWithRootObject:(id)object requiringSecureCoding:(BOOL)requiresSecureCoding error:(NSError **)error API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
使用步骤:
1、遵守协议NSSecureCoding
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface FLPersion : NSObject <NSSecureCoding>
/** 姓名*/
@property (strong, nonatomic) NSString *name;
/** 年龄*/
@property (assign, nonatomic) int age;
@end
NS_ASSUME_NONNULL_END
2、实现协议方法
和NSCoding相比,必须实现一个+ (BOOL)supportsSecureCoding
方法,返回YES,表示支持SecureCoding。
重写了
-initWithCoder
的类应该使用-decodeObjectOfClass:forKey:
而不是-decodeObjectForKey:
设置每一个属性的编码和解码获取相应的值
#import "FLPersion.h"
@implementation FLPersion
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInt:self.age forKey:@"age"];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
self.name = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"name"];
self.age = [aDecoder decodeIntForKey:@"age"];
}
return self;
}
/**
支持加密编码
*/
+ (BOOL)supportsSecureCoding{
return YES;
}
@end
3、实现存取
#import "ViewController.h"
#import "FLPersion.h"
@interface ViewController ()
/** 校验数据*/
@property (strong, nonatomic) NSData *archivedData;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)archiver:(id)sender {
//开始编码
FLPersion *per = [[FLPersion alloc]init];
per.name = @"zhangsan";
per.age = 28;
NSError *error = nil;
self.archivedData = [NSKeyedArchiver archivedDataWithRootObject:per requiringSecureCoding:YES error:&error];
if (self.archivedData == nil || error) {
NSLog(@"归档失败:%@", error);
return;
}
}
- (IBAction)unarchive:(id)sender {
NSError *error = nil;
FLPersion *per = [NSKeyedUnarchiver unarchivedObjectOfClass:[FLPersion class] fromData:self.archivedData error:&error];
if (per == nil || error) {
NSLog(@"解档失败:%@", error);
return;
}
NSLog(@"%@ %ld",per.name,(long)per.age);
}
@end
网友评论