Skip to content

Commit e31c9a6

Browse files
authored
Add NSSecureCoding support for quick implementation macro MJSecureCodingImplementation(class, isSupport). (#821)
1 parent 24087db commit e31c9a6

File tree

6 files changed

+85
-20
lines changed

6 files changed

+85
-20
lines changed

MJExtension/NSObject+MJCoding.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ return self; \
5050
- (void)encodeWithCoder:(NSCoder *)encoder \
5151
{ \
5252
[self mj_encode:encoder]; \
53-
}
53+
}\
54+
55+
#define MJExtensionCodingImplementation MJCodingImplementation
56+
57+
#define MJSecureCodingImplementation(CLASS, FLAG) \
58+
@interface CLASS (MJSecureCoding) <NSSecureCoding> \
59+
@end \
60+
@implementation CLASS (MJSecureCoding) \
61+
MJCodingImplementation \
62+
+ (BOOL)supportsSecureCoding { \
63+
return FLAG; \
64+
} \
65+
@end \
5466

55-
#define MJExtensionCodingImplementation MJCodingImplementation

MJExtension/NSObject+MJCoding.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ - (void)mj_decode:(NSCoder *)decoder
4343
if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return;
4444
if ([ignoredCodingPropertyNames containsObject:property.name]) return;
4545

46-
id value = [decoder decodeObjectForKey:property.name];
46+
// fixed `-[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSNumber'(This will be disallowed in the future.)` warning.
47+
id value = [decoder decodeObjectOfClasses:[NSSet setWithObjects:NSNumber.class, property.type.typeClass, nil] forKey:property.name];
4748
if (value == nil) { // 兼容以前的MJExtension版本
4849
value = [decoder decodeObjectForKey:[@"_" stringByAppendingString:property.name]];
4950
}

MJExtensionTests/MJExtensionTests.m

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#import <CoreData/CoreData.h>
2020
#import "MJFrenchUser.h"
2121
#import "MJCat.h"
22+
#import <MJExtensionTests-Swift.h>
2223

2324
@interface MJExtensionTests : XCTestCase
2425

@@ -440,13 +441,20 @@ - (void)testCoding {
440441
MJBag *bag = [[MJBag alloc] init];
441442
bag.name = @"Red bag";
442443
bag.price = 200.8;
444+
bag.isBig = YES;
445+
bag.weight = 200;
443446

444447
NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:@"bag.data"];
445-
// 归档
446-
[NSKeyedArchiver archiveRootObject:bag toFile:file];
447448

449+
NSError *error = nil;
450+
// 归档
451+
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:bag requiringSecureCoding:YES error:&error];
452+
[data writeToFile:file atomically:true];
453+
448454
// 解档
449-
MJBag *decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
455+
NSData *readData = [NSFileManager.defaultManager contentsAtPath:file];
456+
error = nil;
457+
MJBag *decodedBag = [NSKeyedUnarchiver unarchivedObjectOfClass:MJBag.class fromData:readData error:&error];
450458
MJExtensionLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price);
451459
}
452460

MJExtensionTests/Model/MJBag.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@
1111
@interface MJBag : NSObject
1212
@property (copy, nonatomic) NSString *name;
1313
@property (assign, nonatomic) double price;
14+
@property (nonatomic) BOOL isBig;
15+
@property (nonatomic) NSInteger weight;
1416
@end

MJExtensionTests/Model/MJBag.m

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010

1111
@import MJExtension;
1212

13+
// NSSecureCoding实现
14+
MJSecureCodingImplementation(MJBag, YES)
15+
1316
@implementation MJBag
14-
// NSCoding实现
15-
MJExtensionCodingImplementation
1617

1718
//+ (NSArray *)mj_ignoredCodingPropertyNames
1819
//{

README.md

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ MJExtension
2929
#### ‼️ `@objc` or `objcMembers` attributes should be added to class or property for declaration of Objc accessibility [在 Swift4 之后, 请在属性前加 `@objc` 修饰或在类前增加 `objcMembers`. 以保证 Swift 的属性能够暴露给 Objc 使用. ]‼️
3030
#### ‼️ Use `NSNumber` instead of `Bool`, which is not bridged to `BOOL`. [请勿使用 `Bool` 类型, 因为在 Swift 中并没有桥接该类型, 不能显式的对应 `BOOL`, 请使用 `NSNumber` 替代] ‼️
3131

32-
33-
3432
## Contents
3533

3634
* [Getting Started 【开始使用】](#Getting_Started)
@@ -47,6 +45,7 @@ MJExtension
4745
* [Model array -> JSON array](#Model_array_JSON_array)
4846
* [Core Data](#Core_Data)
4947
* [Coding](#Coding)
48+
* [Secure Coding](#SecureCoding)
5049
* [Camel -> underline](#Camel_underline)
5150
* [NSString -> NSDate, nil -> @""](#NSString_NSDate)
5251
* [NSDate -> NSString](#NSDate_NSString)
@@ -65,7 +64,7 @@ MJExtension
6564
* `JSONString` --> `Model Array``Core Data Model Array`
6665
* `Model Array``Core Data Model Array` --> `JSON Array`
6766
* Coding all properties of a model with only one line of code.
68-
* 只需要一行代码,就能实现模型的所有属性进行Coding(归档和解档)
67+
* 只需要一行代码,就能实现模型的所有属性进行Coding / SecureCoding(归档和解档)
6968

7069
## <a id="Installation"></a> Installation【安装】
7170

@@ -467,40 +466,83 @@ User *user = [User mj_objectWithKeyValues:dict context:context];
467466
[context save:nil];
468467
```
469468

470-
### <a id="Coding"></a> Coding
469+
### <a id="Coding"></a> Coding (Archive & Unarchive methods are deprecated in iOS 12)
471470

472471
```objc
473472
#import "MJExtension.h"
474473

475-
@implementation Bag
474+
@implementation MJBag
476475
// NSCoding Implementation
477-
MJExtensionCodingImplementation
476+
MJCodingImplementation
478477
@end
479478

480479
/***********************************************/
481480

482481
// what properties not to be coded
483-
[Bag mj_setupIgnoredCodingPropertyNames:^NSArray *{
482+
[MJBag mj_setupIgnoredCodingPropertyNames:^NSArray *{
484483
return @[@"name"];
485484
}];
486-
// Equals: Bag.m implements +mj_ignoredCodingPropertyNames method.
485+
// Equals: MJBag.m implements +mj_ignoredCodingPropertyNames method.
487486

488487
// Create model
489-
Bag *bag = [[Bag alloc] init];
488+
MJBag *bag = [[MJBag alloc] init];
490489
bag.name = @"Red bag";
491490
bag.price = 200.8;
492491

493492
NSString *file = [NSHomeDirectory() stringByAppendingPathComponent:@"Desktop/bag.data"];
494-
// Encoding
493+
// Encoding by archiving
495494
[NSKeyedArchiver archiveRootObject:bag toFile:file];
496495

497-
// Decoding
498-
Bag *decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
496+
// Decoding by unarchiving
497+
MJBag *decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
499498
NSLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price);
500499
// name=(null), price=200.800000
501500
```
502501
502+
### <a id="SecureCoding"></a> Secure Coding
503+
504+
Using `MJSecureCodingImplementation(class, isSupport)` macro.
505+
506+
```objc
507+
@import MJExtension;
508+
509+
// NSSecureCoding Implementation
510+
MJSecureCodingImplementation(MJBag, YES)
511+
512+
@implementation MJBag
513+
@end
514+
515+
/***********************************************/
516+
517+
// what properties not to be coded
518+
[MJBag mj_setupIgnoredCodingPropertyNames:^NSArray *{
519+
return @[@"name"];
520+
}];
521+
// Equals: MJBag.m implements +mj_ignoredCodingPropertyNames method.
522+
523+
// Create model
524+
MJBag *bag = [[MJBag alloc] init];
525+
bag.name = @"Red bag";
526+
bag.price = 200.8;
527+
bag.isBig = YES;
528+
bag.weight = 200;
529+
530+
NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:@"bag.data"];
531+
532+
NSError *error = nil;
533+
// Encoding by archiving
534+
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:bag requiringSecureCoding:YES error:&error];
535+
[data writeToFile:file atomically:true];
536+
537+
// Decoding by unarchiving
538+
NSData *readData = [NSFileManager.defaultManager contentsAtPath:file];
539+
error = nil;
540+
MJBag *decodedBag = [NSKeyedUnarchiver unarchivedObjectOfClass:MJBag.class fromData:readData error:&error];
541+
MJExtensionLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price);
542+
```
543+
503544
### <a id="Camel_underline"></a> Camel -> underline【统一转换属性名(比如驼峰转下划线)】
545+
504546
```objc
505547
// Dog
506548
#import "MJExtension.h"

0 commit comments

Comments
 (0)