Skip to content

Commit 33b8b55

Browse files
committed
Custom GULSecureCoding keys support.
1 parent 45f4b67 commit 33b8b55

File tree

2 files changed

+73
-7
lines changed

2 files changed

+73
-7
lines changed

GoogleUtilities/Environment/GULSecureCoding.m

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,37 @@ @implementation GULSecureCoding
2121
+ (nullable id)unarchivedObjectOfClasses:(NSSet<Class> *)classes
2222
fromData:(NSData *)data
2323
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 {
2435
id object;
2536
#if __has_builtin(__builtin_available)
2637
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];
2842
} else
2943
#endif // __has_builtin(__builtin_available)
3044
{
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.
3147
@try {
3248
#pragma clang diagnostic push
3349
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
3450
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
3551
#pragma clang diagnostic pop
3652
unarchiver.requiresSecureCoding = YES;
3753

38-
object = [unarchiver decodeObjectOfClasses:classes forKey:NSKeyedArchiveRootObjectKey];
54+
object = [unarchiver decodeObjectOfClasses:classes forKey:key];
3955
} @catch (NSException *exception) {
4056
if (outError) {
4157
*outError = [self archivingErrorWithException:exception];
@@ -56,16 +72,39 @@ + (nullable id)unarchivedObjectOfClasses:(NSSet<Class> *)classes
5672
+ (nullable id)unarchivedObjectOfClass:(Class)class
5773
fromData:(NSData *)data
5874
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];
6079
}
6180

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 {
6394
NSData *archiveData;
6495
#if __has_builtin(__builtin_available)
6596
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+
}
69108
} else
70109
#endif // __has_builtin(__builtin_available)
71110
{
@@ -91,6 +130,13 @@ + (nullable NSData *)archivedDataWithRootObject:(id<NSCoding>)object error:(NSEr
91130
return archiveData;
92131
}
93132

133+
+ (nullable NSData *)archivedDataWithRootObject:(id<NSCoding>)object
134+
error:(NSError **)outError {
135+
return [self archivedDataWithObject:object
136+
toKey:NSKeyedArchiveRootObjectKey
137+
error:outError];
138+
}
139+
94140
+ (NSError *)archivingErrorWithException:(NSException *)exception {
95141
NSString *failureReason = [NSString
96142
stringWithFormat:@"NSKeyedArchiver exception with name: %@, reason: %@, userInfo: %@",

GoogleUtilities/Environment/Public/GULSecureCoding.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,36 @@ NS_ASSUME_NONNULL_BEGIN
2121
*/
2222
@interface GULSecureCoding : NSObject
2323

24+
/** Decodes an object from archived data to the specified classes with the key `NSKeyedArchiveRootObjectKey`. */
2425
+ (nullable id)unarchivedObjectOfClasses:(NSSet<Class> *)classes
2526
fromData:(NSData *)data
2627
error:(NSError **)outError;
2728

29+
/** Decodes an object from archived data to the specified classes with the given key. */
30+
+ (nullable id)unarchivedObjectOfClasses:(NSSet<Class> *)classes
31+
fromData:(NSData *)data
32+
key:(NSString *)key
33+
error:(NSError **)outError;
34+
35+
/** Decodes an object from archived data to the specified class with the key `NSKeyedArchiveRootObjectKey`. */
2836
+ (nullable id)unarchivedObjectOfClass:(Class)class
2937
fromData:(NSData *)data
3038
error:(NSError **)outError;
3139

40+
/** Decodes an object from archived data to the specified class with the given key. */
41+
+ (nullable id)unarchivedObjectOfClass:(Class)class
42+
fromData:(NSData *)data
43+
key:(NSString *)key
44+
error:(NSError **)outError;
45+
46+
/** Encodes an object to a container with the key `NSKeyedArchiveRootObjectKey`. */
3247
+ (nullable NSData *)archivedDataWithRootObject:(id<NSCoding>)object error:(NSError **)outError;
3348

49+
/** Encodes an object to a container with a given key. */
50+
+ (nullable NSData *)archivedDataWithObject:(id<NSCoding>)object
51+
toKey:(NSString *)key
52+
error:(NSError **)outError;
53+
3454
@end
3555

3656
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)