jayhickey/Cirrus

referencesNotSupported when encoding a [String]? model attribute

Closed this issue · 3 comments

Hi there!

I have a model that conforms to CloudKitCodable. This model has an optional attribute of [String] type:

var tags: [String]?

Yet I get CKRecordEncodingError.referencesNotSupported when encoding the very same optional attribute (which is nil when encoding).

Am I doing something wrong?

Solved this by setting up custom encoder/decoder.

How do I set a custom encoder decoder, when I assign a value to an optional array after synchronization, and then set it to nil, the value will be restored after synchronization

You are right. Once setting a value to an optional attribute and that value is synced to iCloud, it's no possible to set it back to nil and get it synced to iCloud again. It always get synced back with the iCloud value.

What I did is to set up a custom encoder decoder for a Codable struct. See the example below:

`
struct MyModel: Codable {
var id: String
var title: String
var dueDate: Date?

private var proxyDueDate: Data

enum ConfigurationKeys: String, CodingKey {
    case id, title, proxyDueDate
}

public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: ConfigurationKeys.self)
    let decoder = JSONDecoder()

    id = try container.decode(String.self, forKey: .id)
    title = try container.decode(String.self, forKey: .title)
    proxyDueDate = try container.decode(Data.self, forKey: .proxyDueDate)

    let tempDueDate: Date? = try? decoder.decode(Date.self, from: proxyDueDate)
    dueDate = tempDueDate
}

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: ConfigurationKeys.self)
    let encoder: JSONEncoder = .init()
    
    try? container.encode(id, forKey: .id)
    try? container.encode(title, forKey: .title)
    
    let encodedDueDate: Data = try encoder.encode(dueDate)
    try? container.encode(encodedDueDate, forKey: .proxyDueDate)
}

}
`