@@ -21,21 +21,37 @@ @implementation GULSecureCoding
21
21
+ (nullable id )unarchivedObjectOfClasses : (NSSet <Class> *)classes
22
22
fromData : (NSData *)data
23
23
error : (NSError **)outError {
24
+ // Use the default root object key by default.
25
+ return [self unarchivedObjectOfClasses: classes
26
+ fromData: data
27
+ key: NSKeyedArchiveRootObjectKey
28
+ error: outError];
29
+ }
30
+
31
+ + (nullable id )unarchivedObjectOfClasses : (NSSet <Class> *)classes
32
+ fromData : (NSData *)data
33
+ key : (NSString *)key
34
+ error : (NSError **)outError {
24
35
id object;
25
36
#if __has_builtin(__builtin_available)
26
37
if (@available (macOS 10.13 , iOS 11.0 , tvOS 11.0 , watchOS 4.0 , *)) {
27
- object = [NSKeyedUnarchiver unarchivedObjectOfClasses: classes fromData: data error: outError];
38
+ // Pass in the outError explicitly, which will return errors from the unarchiver.
39
+ NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc ] initForReadingFromData: data error: outError];
40
+ unarchiver.requiresSecureCoding = YES ;
41
+ object = [unarchiver decodeObjectOfClasses: classes forKey: key];
28
42
} else
29
43
#endif // __has_builtin(__builtin_available)
30
44
{
45
+ // Before the `error` parameter was available in the `NSKeyedUnarchiver` initializer, it threw an
46
+ // exception. Handle that case explicitly and return an error instead which is safer.
31
47
@try {
32
48
#pragma clang diagnostic push
33
49
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
34
50
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc ] initForReadingWithData: data];
35
51
#pragma clang diagnostic pop
36
52
unarchiver.requiresSecureCoding = YES ;
37
53
38
- object = [unarchiver decodeObjectOfClasses: classes forKey: NSKeyedArchiveRootObjectKey ];
54
+ object = [unarchiver decodeObjectOfClasses: classes forKey: key ];
39
55
} @catch (NSException *exception ) {
40
56
if (outError) {
41
57
*outError = [self archivingErrorWithException: exception ];
@@ -56,16 +72,39 @@ + (nullable id)unarchivedObjectOfClasses:(NSSet<Class> *)classes
56
72
+ (nullable id )unarchivedObjectOfClass : (Class )class
57
73
fromData : (NSData *)data
58
74
error : (NSError **)outError {
59
- return [self unarchivedObjectOfClasses: [NSSet setWithObject: class] fromData: data error: outError];
75
+ return [self unarchivedObjectOfClass: class
76
+ fromData: data
77
+ key: NSKeyedArchiveRootObjectKey
78
+ error: outError];
60
79
}
61
80
62
- + (nullable NSData *)archivedDataWithRootObject : (id <NSCoding >)object error : (NSError **)outError {
81
+ + (nullable id )unarchivedObjectOfClass : (Class )class
82
+ fromData : (NSData *)data
83
+ key : (NSString *)key
84
+ error : (NSError **)outError {
85
+ return [self unarchivedObjectOfClasses: [NSSet setWithObject: class]
86
+ fromData: data
87
+ key: key
88
+ error: outError];
89
+ }
90
+
91
+ + (nullable NSData *)archivedDataWithObject : (id <NSCoding >)object
92
+ toKey : (NSString *)key
93
+ error : (NSError **)outError {
63
94
NSData *archiveData;
64
95
#if __has_builtin(__builtin_available)
65
96
if (@available (macOS 10.13 , iOS 11.0 , tvOS 11.0 , watchOS 4.0 , *)) {
66
- archiveData = [NSKeyedArchiver archivedDataWithRootObject: object
67
- requiringSecureCoding: YES
68
- error: outError];
97
+ @try {
98
+ NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc ] initRequiringSecureCoding: YES ];
99
+ [archiver encodeObject: object forKey: key];
100
+ [archiver finishEncoding ];
101
+
102
+ archiveData = [archiver.encodedData copy ];
103
+ } @catch (NSException *exception ) {
104
+ if (outError) {
105
+ *outError = [self archivingErrorWithException: exception ];
106
+ }
107
+ }
69
108
} else
70
109
#endif // __has_builtin(__builtin_available)
71
110
{
@@ -91,6 +130,13 @@ + (nullable NSData *)archivedDataWithRootObject:(id<NSCoding>)object error:(NSEr
91
130
return archiveData;
92
131
}
93
132
133
+ + (nullable NSData *)archivedDataWithRootObject : (id <NSCoding >)object
134
+ error : (NSError **)outError {
135
+ return [self archivedDataWithObject: object
136
+ toKey: NSKeyedArchiveRootObjectKey
137
+ error: outError];
138
+ }
139
+
94
140
+ (NSError *)archivingErrorWithException : (NSException *)exception {
95
141
NSString *failureReason = [NSString
96
142
stringWithFormat: @" NSKeyedArchiver exception with name: %@ , reason: %@ , userInfo: %@ " ,
0 commit comments