I need to bind a date to a value and save it into Cloudkit. Rather than just save a new CKRecord
for every object and subscript "date" and "value", I would prefer that the CKRecord
is an array of dictionary: [(date, value)]. I've looked around and can't find any examples of this type of Cloudkit data storage. I would have thought by now that Codable would have been bridged over to Cloudkit but I don't see anything indicating that. There is a library that handles this but it doesn't handle this type of nesting. Is there anyway to do this?
Although CKRecord
does have the ability to support an Array
, it is primarily for storing simple data types like strings, numbers, and CKRecord.Reference
. You don't specifically call out what your 'value' type is, but here is an example of using JSONEncoder
/JSONDecoder
to add support for writing/reading any codable type to a CKRecord
. The encoder/decoder is simply converting the Encodable
/Decodable
type to/from a binary Data
representation, which CKRecord
also supports.
private let encoder: JSONEncoder = .init()
private let decoder: JSONDecoder = .init()
extension CKRecord {
func decode<T>(forKey key: FieldKey) throws -> T where T: Decodable {
guard let data = self[key] as? Data else {
throw CocoaError(.coderValueNotFound)
}
return try decoder.decode(T.self, from: data)
}
func encode<T>(_ encodable: T, forKey key: FieldKey) throws where T: Encodable {
self[key] = try encoder.encode(collection)
}
}
Usage would look like the following:
let collection: [[Date: String]] = [[:]]
let record = CKRecord(recordType: "MyRecord")
try? record.encode(collection, forKey: "collection")
let persisted = try? record.decode(forKey: "collection") as [[Date: String]]