diff --git a/MJExtension/NSObject+MJCoding.m b/MJExtension/NSObject+MJCoding.m index ed0a608..614514a 100755 --- a/MJExtension/NSObject+MJCoding.m +++ b/MJExtension/NSObject+MJCoding.m @@ -44,7 +44,11 @@ - (void)mj_decode:(NSCoder *)decoder if ([ignoredCodingPropertyNames containsObject:property.name]) return; // fixed `-[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSNumber'(This will be disallowed in the future.)` warning. - id value = [decoder decodeObjectOfClasses:[NSSet setWithObjects:NSNumber.class, property.type.typeClass, nil] forKey:property.name]; + Class genericClass = [property objectClassInArrayForClass:property.srcClass]; + // If genericClass exists, property.type.typeClass would be a collection type(Array, Set, Dictionary). This scenario([obj, nil, obj, nil]) would not happened. + NSSet *classes = [NSSet setWithObjects:NSNumber.class, + property.type.typeClass, genericClass, nil]; + id value = [decoder decodeObjectOfClasses:classes forKey:property.name]; if (value == nil) { // 兼容以前的MJExtension版本 value = [decoder decodeObjectForKey:[@"_" stringByAppendingString:property.name]]; } diff --git a/MJExtensionTests/MJExtensionTests.m b/MJExtensionTests/MJExtensionTests.m index 2b123d5..e0df008 100644 --- a/MJExtensionTests/MJExtensionTests.m +++ b/MJExtensionTests/MJExtensionTests.m @@ -20,6 +20,7 @@ #import "MJFrenchUser.h" #import "MJCat.h" #import +#import "MJPerson.h" @interface MJExtensionTests : XCTestCase @@ -458,6 +459,42 @@ - (void)testCoding { MJExtensionLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price); } +- (void)testCodingModelArrayProperty { + // 有 NSArray 属性 模型 + MJPerson *person = [[MJPerson alloc] init]; + person.name = @"boy1"; + person.isVIP = YES; + + MJPerson *friend1 = [[MJPerson alloc] init]; + friend1.name = @"friend1"; + friend1.isVIP = YES; + + MJPerson *friend2 = [[MJPerson alloc] init]; + friend2.name = @"friend2"; + friend2.isVIP = NO; + + person.friends = @[friend1, friend2]; + person.books = @[@"book1", @"book2"]; + + NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:@"person.data"]; + NSError *error = nil; + // 归档 + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person + requiringSecureCoding:YES + error:&error]; + BOOL write = [data writeToFile:file atomically:true]; + XCTAssert(write); + + // 解档 + NSData *readData = [NSFileManager.defaultManager contentsAtPath:file]; + error = nil; + MJPerson *decodedPerson = [NSKeyedUnarchiver unarchivedObjectOfClass:MJPerson.class + fromData:readData + error:&error]; + XCTAssert(decodedPerson.friends.count == 2); + XCTAssert(decodedPerson.books.count == 2); +} + #pragma mark 统一转换属性名(比如驼峰转下划线) - (void)testReplacedKeyFromPropertyName121 { // 1.定义一个字典 diff --git a/MJExtensionTests/Model/MJPerson.h b/MJExtensionTests/Model/MJPerson.h index 67f345f..5c763d9 100644 --- a/MJExtensionTests/Model/MJPerson.h +++ b/MJExtensionTests/Model/MJPerson.h @@ -12,7 +12,9 @@ NS_ASSUME_NONNULL_BEGIN @interface MJPerson : NSObject @property (copy, nonatomic) NSString *name; +@property (nonatomic) BOOL isVIP; @property (strong, nonatomic) NSArray *friends; +@property (strong, nonatomic) NSArray *books; @end NS_ASSUME_NONNULL_END diff --git a/MJExtensionTests/Model/MJPerson.m b/MJExtensionTests/Model/MJPerson.m index 55644f0..3c59c80 100644 --- a/MJExtensionTests/Model/MJPerson.m +++ b/MJExtensionTests/Model/MJPerson.m @@ -9,8 +9,12 @@ #import "MJPerson.h" #import +// NSSecureCoding实现 +MJSecureCodingImplementation(MJPerson, YES) + @implementation MJPerson + (NSDictionary *)mj_objectClassInArray { - return @{@"friends" : @"MJPerson"}; + return @{@"friends": [MJPerson class], + @"books": [NSString class]}; } @end