NSCoding
是一種非安全的編解碼方式宝穗,使用NSKeyedArchiver
歸檔自定義類對象做持久化存儲眠冈。由于未做數(shù)據校驗洲尊,可通過篡改本地存儲的信息進行攻擊晓锻。從IOS 6.0之后引入了NSSecureCoding
來保證數(shù)據安全盅称。
NSSecureCoding
協(xié)議繼承自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混狠、遵守協(xié)議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、實現(xiàn)協(xié)議方法
和NSCoding相比疾层,必須實現(xiàn)一個+ (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予弧、實現(xiàn)存取
#import "ViewController.h"
#import "FLPersion.h"
@interface ViewController ()
/** 校驗數(shù)據*/
@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