My app uses core data, which stores instances of a custom class CustomClass
.
This class has a number of properties, most of them of standard types, but one property is xxx: Set<CustomObject>
.
The xcdatamodeld
thus specifies (among the others with standard types) an attribute xxx
of type Transformable
. xxx
is the Set<CustomObject>
.
Its type is Optional
and the Transformer is now NSSecureUnarchiveFromData
.
Earlier the Transformer was not specified, and thus decoding was not secure. But Apple now advises to use secure coding, since insecure coding will be deprecated in future.
To enable secure coding, I did the following:
CustomClass
now adopts NSSecureCoding
instead of NSCoding
.
The following var
was added to CustomClass
:
public static var supportsSecureCoding: Bool { get { return true } }
Then I tried to modify public required convenience init?(coder aDecoder: NSCoder) {…}
so that attribute xxx
is securely decoded. I know that instead of
let xxx = aDecoder.decodeObject(forKey: „xxx“) as? Set<CustomObject>
I have to use now decodeObject(of:forKey:)
, where of
is the type of the object to be decoded, here type Set<CustomObject>
.
My problem is that I don’t know how to formulate this: If I use
let xxx = aDecoder.decodeObject(of: Set<CustomObject>.self, forKey: „xxx“)
I get the error Cannot convert value of type 'Set<CustomObject>.Type' to expected argument type '[AnyClass]?' (aka 'Optional<Array<AnyObject.Type>>‘)
.
Apparently the compiler did not compile
func decodeObject<DecodedObjectType>(of cls: DecodedObjectType.Type, forKey key: String) -> DecodedObjectType? where DecodedObjectType : NSObject, DecodedObjectType : NSCoding
but instead
func decodeObject(of classes: [AnyClass]?, forKey key: String) -> Any?
i.e. it treated Set<CustomObject>
not as a single type, but as a collection of types.
So, how do I specify that only a single type should be decoded, namely Set<CustomObject>
?
Unfortunately, I could not find anything in the Apple docs, but I found a hint to the solution in this post:
NSSecureCoding
is not available for all standard swift classes. For those classes, that don’t support it, one has to use the Objective-C counterpart classes, i.e. NSString
instead of String
.
One example: If var string = "String"
has to be securely encoded, one has to use e.g. aCoder.encode(string as NSString, forKey: „string“)
.
Now currently Set
is not supported by NSSecureCoding
. I had to use thus
let aSet: Set<CustomObject> = []
aCoder.encode(aSet as NSSet, forKey: „aSet“)
and
let decodedSet = aDecoder.decodeObject(of: NSSet.self, forKey: „aSet“) as? Set<CustomObject>