This is very similar to this question: How can I decode an object when original class is not available?, but what's the best way to do this if the data I am unarchiving could be any class conforming to a certain protocol?
As a simple example,
protocol TestProtocol: NSCoding { }
class A: TestProtocol { }
class B: TestProtocol { }
class C: TestProtocol { }
// And 20 more classes
...
let data = UserDefaults.standard.object(forKey: "TestKey") as! Data
NSKeyedUnarchiver.setClass(<SomeClassConformingToTestProtocol?>, forClassName: String(describing: <SomeClassConformingToTestProtocol>)) // No class to pass in here, but protocol is known.
NSKeyedUnarchiver.unarchiveObject(with: data) as! TestProtocol
I could loop through every class and call
NSKeyedUnarchiver.setClass(A.self, forClassName: "A")
NSKeyedUnarchiver.setClass(B.self, forClassName: "B")
NSKeyedUnarchiver.setClass(C.self, forClassName: "C")
But that means whenever there is a new class in TestProtocol
, it needs to be added to this list and seems unenforceable.
I've tried overriding classFallbacksForKeyedArchiver()
to provide a fallback class name if the original class is not found, but this is still throwing an NSInvalidUnarchiveOperationException
when unarchiving in my project's Share Extension.
Is there a better way to do this other than to remembering to add classes to an array when a new class (conforming to a protocol) is created?