#ios #swift #nsmanagedobject #decodable
#iOS #swift #nsmanagedobject #декодируемый
Вопрос:
У меня есть следующая универсальная функция, которая работает: она корректно создает объекты, и я знаю, что она сохраняется в core data, потому что, если выполнить запрос на выборку сразу после этого, я получу объект, который я только что создал. Однако сам объект не является допустимым объектом core data (ошибка x-core data). Есть ли какой-либо обходной путь, чтобы мне не приходилось выполнять запрос на выборку сразу после декодирования объекта? Большое спасибо.
func decode<T: Decodable>(data: Data?, objectType: T.Type, save: Bool = true, completionHandler: @escaping (T) -> ())
{
guard let d = data else { return }
do
{
let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
privateContext.parent = SingletonDelegate.shared.context
let root = try JSONDecoder(context: privateContext).decode(objectType, from: d)
if save
{
try privateContext.save()
privateContext.parent?.performAndWait
{
do
{
if let p = privateContext.parent
{
try p.save()
}
}catch
{
print(error)
}
}
}
DispatchQueue.main.async
{
completionHandler(root)
}
}catch
{
print(error)
}
}
extension CodingUserInfoKey
{
static let context = CodingUserInfoKey(rawValue: "context")!
}
extension JSONDecoder
{
convenience init(context: NSManagedObjectContext)
{
self.init()
self.userInfo[.context] = context
}
}
Ответ №1:
Ошибка core data является допустимым объектом Core Data; он просто еще не был извлечен из резервного хранилища в память.
Чтобы уменьшить использование памяти, Core Data извлекает полный объект только при доступе к одному из его свойств. Эта выборка выполняется автоматически и эффективно прозрачна для вашего кода.
Это означает, что вам не нужно делать ничего особенного; вы можете просто использовать управляемый объект.
Комментарии:
1. Спасибо за ответ. Когда я печатаю атрибут объекта, он пуст
2. Откуда берется
JSONDecoder(context:)
инициализатор? Вы добавили расширение кJSONDecoder
?3. Да, я добавил его в вопрос. Я пытаюсь верстать архитектуру VIPER, и в хранилище все в порядке (без сбоев). Однако на рабочем сервере, который обрабатывает это хранилище (переданное closures), оно пустое (ошибка).
4. Ошибка не является пустой; она просто представляет объект, который еще не был извлечен. Доступ к свойству должен вызвать сбой. Совпадает ли идентификатор объекта ошибки с идентификатором объекта, который вы получаете при выполнении выборки? Проблема может заключаться в том, что вы создаете объект в дочернем хранилище; Объекты в дочернем хранилище не сохраняются в постоянном хранилище. Это делает родительский контекст. Возможно, вам потребуется использовать
object(with:)
в родительском хранилище, чтобы получить нужный вам объект5. Нет, на самом деле это не то же самое. ObjectId декодированного объекта имеет дополнительный /, а хэш начинается с t.