#ios #swift #icloud #cloudkit #ckrecord
#iOS #swift #icloud #cloudkit #ckrecord
Вопрос:
Мне нужно привязать дату к значению и сохранить ее в Cloudkit. Вместо того, чтобы просто сохранять новый CKRecord
для каждого объекта и подстрочного индекса «дата» и «значение», я бы предпочел, чтобы CKRecord
это был массив dictionary: [(дата, значение)]. Я осмотрелся и не могу найти никаких примеров такого типа хранилища данных Cloudkit. Я бы уже подумал, что Codable был бы соединен с Cloudkit, но я не вижу ничего, указывающего на это. Существует библиотека, которая обрабатывает это, но она не обрабатывает этот тип вложенности. Есть ли какой-нибудь способ сделать это?
Ответ №1:
Хотя CKRecord
есть возможность поддерживать Array
, это в первую очередь для хранения простых типов данных, таких как строки, числа и CKRecord.Reference
. Вы специально не указываете, какой у вас тип значения, но вот пример использования JSONEncoder
/ JSONDecoder
для добавления поддержки записи / чтения любого кодируемого типа в CKRecord
. Кодировщик / декодер просто преобразует Encodable
/ Decodable
тип в / из двоичного Data
представления, которое CKRecord
также поддерживает.
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)
}
}
Использование будет выглядеть следующим образом:
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]]