Convert Swift Encodable class typed as Any to dictionary

后端 未结 2 447
暗喜
暗喜 2021-01-22 10:17

In connection with my previous questions, I decided to subclass NSArrayController in order to achieve the desired behavior.

class NSPresetArrayContr         


        
2条回答
  •  轮回少年
    2021-01-22 10:50

    The problem is that protocols don't always conform to themselves. PropertyListEncoder's encode(_:) method expects a Value : Encodable argument:

    func encode(_ value: Value) throws -> Data
    

    However the Encodable type itself is currently unable to satisfy this constraint (but it might well do in a future version of the language).

    As explored in the linked Q&A (and also here), one way to work around this limitation is to open the Encodable value in order to dig out the underlying concrete type, which we can substitute for Value. We can do this with a protocol extension, and use a wrapper type in order to encapsulate it:

    extension Encodable {
      fileprivate func openedEncode(to container: inout SingleValueEncodingContainer) throws {
        try container.encode(self)
      }
    }
    
    struct AnyEncodable : Encodable {
      var value: Encodable
      init(_ value: Encodable) {
        self.value = value
      }
      func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try value.openedEncode(to: &container)
      }
    }
    

    Applied to your example:

    class NSPresetArrayController : NSArrayController {
      override func addObject(_ object: Any) {
        guard let object = object as? Encodable else { 
          // Not encodable, maybe do some error handling.
          return 
        }
        do {
          let encoded = try PropertyListEncoder().encode(AnyEncodable(object))
          let cocoaPropertyList = try PropertyListSerialization.propertyList(from: encoded, format: nil)
          super.addObject(cocoaPropertyList)
        } catch {
          // Couldn't encode. Do some error handling.
        }
      }
    }
    

提交回复
热议问题