Xcode 13 and iOS 15 began warning about missingAllowedClasses when using custom DataTransformers. There is very little documentation on custom DataTransformers, so I thought I would post a question and answer it here.
[general] *** -[NSKeyedUnarchiver _warnAboutPlistType:missingInAllowedClasses:] allowed unarchiving safe plist type ''NSString' (0x1dc9a7660) [/System/Library/Frameworks/Foundation.framework]', even though it was not explicitly included in the client allowed classes set: '{(
"'NSArray' (0x1dc99c838) [/System/Library/Frameworks/CoreFoundation.framework]"
)}'. This will be disallowed in the future.
Notice in the warning message, it specifies 'NSArray' and the type missing, 'NSString'.
I faced this issue for userDefaults
while saving custom models, and I fixed it by passing classes of [NSArray.self, NSString.self,NSNumber.self,CustomModel.self]
to silence this warning.
Note: before iOS 15 I just passed an NSArray
class, but now I have to pass other classes like NSString
or NSNumber
because my custom model has strings, numbers and arrays.
{
decodeData = try NSKeyedUnarchiver.unarchivedObject(
ofClasses: [NSArray.self, NSString.self, NSNumber.self, CustomModel.self], from: customModel
) as? [CustomModel]
}
Here is an array value transformer that received the new warning, but no longer does since NSString was added:
// 1. Subclass from `NSSecureUnarchiveFromDataTransformer`
@objc(ArrayValueTransformer)
final class ArrayValueTransformer: NSSecureUnarchiveFromDataTransformer {
static let name = NSValueTransformerName(rawValue: String(describing: ArrayValueTransformer.self))
// 2. Make sure `NSArray` is in the allowed class list. However, since the array can also contain strings, be sure to include NSString.self in the allowedTopLevelClasses
override static var allowedTopLevelClasses: [AnyClass] {
return [NSArray.self, NSString.self] // Added NSString.self here to fix warning
}
/// Registers the transformer.
public static func register() {
let transformer = ArrayValueTransformer()
ValueTransformer.setValueTransformer(transformer, forName: name)
}
}
You can also silence warnings if using:
return try? NSKeyedUnarchiver.unarchivedObject(ofClasses:from:)
by passing the same array that is specified in the return of allowedTopLevelClasses
to the ofClasses
parameter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With