2

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?

Cody
  • 650
  • 9
  • 16
  • How do you encode the object? If you know the class you use for encoding, then you should be able to use it for decoding. – Cristik Oct 03 '19 at 18:12
  • @Cristik Good question, I don't know the class for encoding either, so I'm also looping through each class and calling `NSKeyedArchiver.setClassName("A", for: A.self) ...` too. – Cody Oct 04 '19 at 17:53
  • Who's doing the encoding? You or someone else? Do you have control over the encoding code? – Cristik Oct 04 '19 at 17:55
  • Yes I am doing the encoding, and yes I do have control over the encoding code. The `TestProtocol` also conforms to `NSCoding` – Cody Oct 04 '19 at 18:00
  • You can't encode protocols, though, you need a concrete class for that. Your `TestProtocol` actually is inheriting `NSCopying` instead of conforming to it. – Cristik Oct 04 '19 at 18:01
  • Sorry I meant `TestProtocol` inherits `NSCoding` instead of conforming to it. The classes that conform to `TestProtocol` conform to `NSCoding` as well. – Cody Oct 04 '19 at 18:04
  • Also, if you have control over the encoding code, you can also store the class name used for encoding and use `NSClassFromName` on the decoding side. – Cristik Oct 04 '19 at 18:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/200412/discussion-between-cody-and-cristik). – Cody Oct 04 '19 at 18:11

0 Answers0