diff --git a/MJExtension.xcodeproj/project.pbxproj b/MJExtension.xcodeproj/project.pbxproj index ce4ef10..fb22921 100644 --- a/MJExtension.xcodeproj/project.pbxproj +++ b/MJExtension.xcodeproj/project.pbxproj @@ -57,6 +57,8 @@ 2D2DBA832317DBE0005A689E /* MJAd.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D2DBA732317DBDF005A689E /* MJAd.m */; }; 2D2DBA842317DBE0005A689E /* MJExtensionConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D2DBA752317DBDF005A689E /* MJExtensionConfig.m */; }; 2D2DBA852317DBE0005A689E /* MJPerson.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D2DBA772317DBDF005A689E /* MJPerson.m */; }; + BF76218C2FE4C63A008FC9C3 /* MJWife.m in Sources */ = {isa = PBXBuildFile; fileRef = BF76218B2FE4C63A008FC9C3 /* MJWife.m */; }; + BF76218F2FE4C700008FC9C3 /* MJWomen.m in Sources */ = {isa = PBXBuildFile; fileRef = BF76218E2FE4C700008FC9C3 /* MJWomen.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -140,6 +142,10 @@ 2D2DBA762317DBDF005A689E /* MJBook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJBook.h; sourceTree = ""; }; 2D2DBA772317DBDF005A689E /* MJPerson.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJPerson.m; sourceTree = ""; }; 2D2DBA872317DCCF005A689E /* PrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrefixHeader.pch; sourceTree = ""; }; + BF76218A2FE4C63A008FC9C3 /* MJWife.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MJWife.h; sourceTree = ""; }; + BF76218B2FE4C63A008FC9C3 /* MJWife.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MJWife.m; sourceTree = ""; }; + BF76218D2FE4C700008FC9C3 /* MJWomen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MJWomen.h; sourceTree = ""; }; + BF76218E2FE4C700008FC9C3 /* MJWomen.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MJWomen.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -304,6 +310,10 @@ 2D2DBA6E2317DBDF005A689E /* MJUser.m */, 0130EE7E233C56D8008D2386 /* MJFrenchUser.h */, 0130EE7F233C56D8008D2386 /* MJFrenchUser.m */, + BF76218A2FE4C63A008FC9C3 /* MJWife.h */, + BF76218B2FE4C63A008FC9C3 /* MJWife.m */, + BF76218D2FE4C700008FC9C3 /* MJWomen.h */, + BF76218E2FE4C700008FC9C3 /* MJWomen.m */, ); path = Model; sourceTree = ""; @@ -488,6 +498,7 @@ buildActionMask = 2147483647; files = ( 2D2DBA812317DBE0005A689E /* MJStatusResult.m in Sources */, + BF76218F2FE4C700008FC9C3 /* MJWomen.m in Sources */, 2D2DBA7C2317DBE0005A689E /* MJStudent.m in Sources */, 2D2DBA822317DBE0005A689E /* MJStatus.m in Sources */, 2D2DBA832317DBE0005A689E /* MJAd.m in Sources */, @@ -507,6 +518,7 @@ 2D2DBA7D2317DBE0005A689E /* MJBook.m in Sources */, 0107507E26E890C100AAEA10 /* CoreDataTests.swift in Sources */, 0107507826E88DD400AAEA10 /* MJCoreDataTestModel.xcdatamodeld in Sources */, + BF76218C2FE4C63A008FC9C3 /* MJWife.m in Sources */, 2D2DBA7A2317DBE0005A689E /* MJDog.m in Sources */, 01052EAD25F872D00049EC6F /* MultiThreadTests.swift in Sources */, ); diff --git a/MJExtension/NSObject+MJCoding.m b/MJExtension/NSObject+MJCoding.m index 614514a..85a46a4 100755 --- a/MJExtension/NSObject+MJCoding.m +++ b/MJExtension/NSObject+MJCoding.m @@ -44,7 +44,7 @@ - (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. - Class genericClass = [property objectClassInArrayForClass:property.srcClass]; + Class genericClass = [property objectClassInArrayForClass:[self class]]; // 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]; diff --git a/MJExtensionTests/MJExtensionTests.m b/MJExtensionTests/MJExtensionTests.m index e0df008..9d78e00 100644 --- a/MJExtensionTests/MJExtensionTests.m +++ b/MJExtensionTests/MJExtensionTests.m @@ -21,6 +21,7 @@ #import "MJCat.h" #import #import "MJPerson.h" +#import "MJWife.h" @interface MJExtensionTests : XCTestCase @@ -495,6 +496,45 @@ - (void)testCodingModelArrayProperty { XCTAssert(decodedPerson.books.count == 2); } +- (void)testCodingModelArrayPropertyInInherit { + // 有 NSArray 属性 模型 + MJWife *wife = [[MJWife alloc] init]; + wife.name = @"Rose"; + wife.weight = 66.0; + + MJBag *bag1 = [[MJBag alloc] init]; + bag1.name = @"小书包1"; + bag1.price = 205; + + MJBag *bag2 = [[MJBag alloc] init]; + bag2.name = @"小书包2"; + bag2.price = 205; + + wife.books = @[@"book1", @"book2"]; + wife.bags = @[bag1, bag2]; + + NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:@"wife.data"]; + NSError *error = nil; + // 归档 + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:wife + requiringSecureCoding:YES + error:&error]; + XCTAssert(!error); + BOOL write = [data writeToFile:file atomically:true]; + XCTAssert(write); + + // 解档 + NSData *readData = [NSFileManager.defaultManager contentsAtPath:file]; + error = nil; + MJWife *decodedWife = [NSKeyedUnarchiver unarchivedObjectOfClass:[MJWife class] + fromData:readData + error:&error]; + XCTAssert(!error); + XCTAssert(decodedWife.books.count == 2); + XCTAssert(decodedWife.bags.count == 2); +} + + #pragma mark 统一转换属性名(比如驼峰转下划线) - (void)testReplacedKeyFromPropertyName121 { // 1.定义一个字典 diff --git a/MJExtensionTests/Model/MJWife.h b/MJExtensionTests/Model/MJWife.h new file mode 100644 index 0000000..95c19b0 --- /dev/null +++ b/MJExtensionTests/Model/MJWife.h @@ -0,0 +1,21 @@ +// +// MJWife.h +// MJExtensionTests +// +// Created by touchWorld on 2026/6/19. +// Copyright © 2026 MJ Lee. All rights reserved. +// + +#import +#import "MJWomen.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MJWife : MJWomen + +@property (nonatomic, assign) double weight; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/MJExtensionTests/Model/MJWife.m b/MJExtensionTests/Model/MJWife.m new file mode 100644 index 0000000..057304b --- /dev/null +++ b/MJExtensionTests/Model/MJWife.m @@ -0,0 +1,14 @@ +// +// MJWife.m +// MJExtensionTests +// +// Created by touchWorld on 2026/6/19. +// Copyright © 2026 MJ Lee. All rights reserved. +// + +#import "MJWife.h" + +@implementation MJWife + +@end + diff --git a/MJExtensionTests/Model/MJWomen.h b/MJExtensionTests/Model/MJWomen.h new file mode 100644 index 0000000..891888c --- /dev/null +++ b/MJExtensionTests/Model/MJWomen.h @@ -0,0 +1,23 @@ +// +// MJWomen.h +// MJExtensionTests +// +// Created by touchWorld on 2026/6/19. +// Copyright © 2026 MJ Lee. All rights reserved. +// + +#import +#import "MJBag.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MJWomen : NSObject + +@property (nonatomic, copy) NSString *name; +@property (strong, nonatomic) NSArray *books; +@property (nonatomic, strong) NSArray *bags; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/MJExtensionTests/Model/MJWomen.m b/MJExtensionTests/Model/MJWomen.m new file mode 100644 index 0000000..12fb632 --- /dev/null +++ b/MJExtensionTests/Model/MJWomen.m @@ -0,0 +1,22 @@ +// +// MJWomen.m +// MJExtensionTests +// +// Created by touchWorld on 2026/6/19. +// Copyright © 2026 MJ Lee. All rights reserved. +// + +#import "MJWomen.h" +#import + +// NSSecureCoding实现 +MJSecureCodingImplementation(MJWomen, YES) + +@implementation MJWomen + ++ (NSDictionary *)mj_objectClassInArray { + return @{@"books": [NSString class], + @"bags": [MJBag class]}; +} + +@end