This repository was written based on this book.
- Your First Core Data App
- NSManagedObject Subclasses
- The Core Data Stack
- Intermediate Fetching
- NSFetchedResultsController
- Versioning & Migration
- Unit Testing
- Measuring & Boosting Performance
- Multiple Managed Object Contexts
- NSPersistentCloudKitContainer
- example
- Core Data обеспечивает постоянство на диске, что означает, что ваши данные будут доступны даже после завершения работы вашего приложения или выключения вашего устройства. Это отличается от постоянства в памяти, при котором ваши данные будут сохраняться только до тех пор, пока ваше приложение находится в памяти, либо на переднем плане, либо в фоновом режиме.
- Xcode поставляется с мощным редактором модели данных, который можно использовать для создания управляемой объектной модели. Модель управляемого объекта состоит из сущностей, атрибутов и отношений.
- Entity - это определение класса в Core Data.
- Attribute - это часть информации, прикрепленная к объекту.
- Relationship - это связь между несколькими объектами.
- NSManagedObject - это представление сущности Core Data во время выполнения. Вы можете читать и записывать в его атрибуты, используя Key-Value Coding(кодирование значения ключа).
- Вам нужен NSManagedObjectContext для save() или fetch(_ :) данных в Core Data и из них.
- example
- Core Data поддерживает различные типы данных атрибутов, которые определяют, какие данные вы можете хранить в своих объектах, и сколько места они будут занимать на диске. Некоторые общие типы данных атрибутов: String, Date и Double.
- Тип данных атрибута Binary Data дает вам возможность хранить произвольные объемы двоичных данных в вашей модели данных.
- Тип данных атрибута Transformable позволяет хранить любой объект, соответствующий NSSecureCoding, в вашей модели данных.
- Использование подкласса NSManagedObject - лучший способ работы с сущностью Core Data. Вы можете либо сгенерировать подкласс вручную, либо позволить Xcode сделать это автоматически.
- Вы можете уточнить набор сущностей, извлеченных NSFetchRequest, используя NSPredicate.
- Вы можете установить правила проверки (например, максимальное значение и минимальное значение) для большинства типов данных атрибутов непосредственно в редакторе модели данных. Контекст управляемого объекта вызовет ошибку, если вы попытаетесь сохранить недопустимые данные.
- example
- Core Data Stack. Стек основных данных состоит из пяти классов:
- NSManagedObjectModel
- NSPersistentStore
- NSPersistentStoreCoordinator
- NSManagedObjectContext
- NSPersistentContainer - объединяет все вместе.
- Managed object model. Модель управляемых объектов представляет каждый тип объекта в модели данных вашего приложения, свойства, которые они могут иметь, и отношения между ними.
- Persistent store. Постоянное хранилище может поддерживаться базой данных SQLite (по умолчанию), XML, двоичным файлом или хранилищем в памяти. Вы также можете предоставить собственное хранилище резервных копий с помощью API инкрементного хранилища.
- Persistent store coordinator. Координатор постоянного хранилища скрывает детали реализации того, как настроены ваши постоянные хранилища, и представляет простой интерфейс для контекста управляемого объекта.
- Managed object context. Контекст управляемого объекта управляет жизненными циклами управляемых объектов, которые он создает или извлекает. Они несут ответственность за выборку, редактирование
Рассмотрим пять различных способов настроить запрос на получение, чтобы вас не застали врасплох:
// 1
let fetchRequest1 = NSFetchRequest<Venue>()
let entity =
NSEntityDescription.entity(forEntityName: "Venue",
in: managedContext)!
fetchRequest1.entity = entity
// 2
let fetchRequest2 = NSFetchRequest<Venue>(entityName: "Venue")
// 3
let fetchRequest3: NSFetchRequest<Venue> = Venue.fetchRequest()
// 4
let fetchRequest4 = managedObjectModel.fetchRequestTemplate(forName: "venueFR")
// 5
let fetchRequest5 =
managedObjectModel.fetchRequestFromTemplate(
withName: "venueFR",
substitutionVariables: ["NAME" : "Vivi Bubble Tea"])
1
Вы инициализируете экземпляр NSFetchRequest как универсальный тип: NSFetchRequest . Как минимум, вы должны указать NSEntityDescription для запроса на выборку. В данном случае это объект Venue. Вы инициализируете экземпляр NSEntityDescription и используете его для установки свойства объекта запроса на выборку.
2
Здесь вы используете удобный инициализатор NSFetchRequest. Он инициализирует новый запрос на выборку и устанавливает свойство объекта за один шаг. Вам просто нужно предоставить строку для имени объекта, а не полноценное NSEntityDescription.
3
Так же, как второй пример был сокращением первого, третий - сокращением второго. Когда вы генерируете подкласс NSManagedObject, этот шаг также генерирует метод класса, который возвращает NSFetchRequest, уже настроенный для выборки соответствующих типов сущностей. Отсюда и происходит Venue.fetchRequest(). Этот код находится в Venue+CoreDataProperties.swift.
4
В четвертом примере вы получаете запрос на выборку из модели NSManagedObjectModel. Вы можете настроить и сохранить часто используемые запросы на выборку в редакторе модели данных Xcode.
5
Последний случай аналогичен четвертому. Получите запрос на выборку из вашей управляемой объектной модели, но на этот раз вы передадите некоторые дополнительные переменные. Эти переменные «подстановки» используются в предикате для уточнения полученных результатов.
NSFetchRequest | |
---|---|
.managedObjectResultType | возвращает управляемые объекты (значение по умолчанию). |
.countResultType | возвращает количество объектов, соответствующих запросу на выборку. |
.dictionaryResultType | это универсальный возвращаемый тип для возврата результатов различных вычислений. |
.managedObjectIDResultType | возвращает уникальные идентификаторы вместо полноценных управляемых объектов. |
Example
let fetchRequest = NSFetchRequest<NSDictionary>(entityName: "Data")
fetchRequest.resultType = .dictionaryResultType
- example
- NSFetchRequest - это общий тип. Он принимает параметр типа, который указывает тип объектов, которые вы ожидаете получить в результате запроса на выборку.
- Если вы планируете повторно использовать один и тот же тип выборки в разных частях приложения, рассмотрите возможность использования редактора модели данных для хранения неизменяемого запроса выборки непосредственно в вашей модели данных.
- Используйте тип результата счетчика NSFetchRequest, чтобы эффективно вычислять и возвращать счетчики из SQLite.
- Используйте тип результата словаря NSFetchRequest, чтобы эффективно вычислять и возвращать средние, суммы и другие общие вычисления из SQLite.
- Запрос на выборку использует различные методы, такие как использование размеров пакетов, ограничений пакетов и ошибок, чтобы ограничить объем возвращаемой информации.
- Добавьте описание сортировки в запрос на выборку, чтобы эффективно отсортировать полученные результаты.
- Получение большого количества информации может заблокировать основной поток. Используйте NSAsynchronousFetchRequest, чтобы передать часть этой работы фоновому потоку.
- NSBatchUpdateRequest и NSBatchDeleteRequest сокращают количество времени и памяти, необходимые для обновления или удаления большого количества записей в Core Data.
- example
- NSFetchedResultsController абстрагирует большую часть кода, необходимого для синхронизации табличного представления с базовым хранилищем данных.
- По своей сути NSFetchedResultsController является оболочкой вокруг NSFetchRequest и контейнером для полученных результатов.
- Контроллер полученных результатов требует установки по крайней мере одного дескриптора сортировки в своем запросе на выборку. Если вы забудете дескриптор сортировки, ваше приложение выйдет из строя.
- Вы можете настроить контроллер sectionNameKeyPath для полученного результата, чтобы указать атрибут для группировки результатов в разделы табличного представления. Каждое уникальное значение соответствует отдельному разделу представления таблицы.
- Группировка набора полученных результатов по разделам - дорогостоящая операция. Избегайте многократного вычисления разделов, указав имя кеша в выбранном контроллере результатов.
- Контроллер выбранных результатов может отслеживать изменения в своем наборе результатов и уведомлять своего делегата NSFetchedResultsControllerDelegate, чтобы тот ответил на эти изменения.
- NSFetchedResultsControllerDelegate отслеживает изменения в отдельных записях Core Data (были ли они вставлены, удалены или изменены), а также изменения целых разделов.
- Дифференцируемые источники данных упрощают работу с контроллерами выбранных результатов и табличными представлениями.
- example
- Миграция необходима, когда вам нужно внести изменения в модель данных.
- Используйте самый простой из возможных методов миграции.
- Облегченная миграция - это термин Apple, обозначающий миграцию с наименьшим объемом работы с вашей стороны.
- По описанию Apple, тяжелые миграции могут включать несколько различных типов пользовательской миграции.
- Пользовательские миграции позволяют вам создать модель сопоставления, чтобы направить Core Data для внесения более сложных изменений, которые легковесные не могут сделать автоматически.
- После создания картографической модели не изменяйте целевую модель.
- Пользовательские миграции вручную идут на один шаг дальше от модели сопоставления и позволяют изменять модель из кода.
- Полностью ручная миграция позволяет вашему приложению последовательно мигрировать от одной версии к другой, предотвращая проблемы, если пользователь пропускает обновление своего устройства до промежуточной версии.
- Миграционное тестирование сложно, потому что оно зависит от данных из исходного хранилища. Обязательно протестируйте несколько сценариев, прежде чем выпускать приложение в App Store.
- example
- Unit tests должны следовать принципам FIRST: быстро, изолированно, повторяемо, самопроверяемся и своевременно.
- Создайте persistent store(постоянное хранилище), специально предназначенное для модульного тестирования, и сбрасывайте его содержимое с каждым тестом. Использование хранилища SQLite в памяти - самый простой подход.
- Core Data может использоваться асинхронно и легко тестируются с помощью класса XCTestExpectation.
- example
- Большинство реализаций Core Data уже являются быстрыми и легкими из-за встроенных оптимизаций Core Data, таких как устранение неисправностей.
- При улучшении производительности Core Data вы должны измерить, внести целевые изменения, а затем измерить еще раз, чтобы убедиться, что ваши изменения оказали желаемое влияние.
- Небольшие изменения в модели данных, такие как перемещение больших двоичных объектов в другие объекты, могут повысить производительность.
- Для оптимальной производительности вы должны ограничить объем данных, которые вы извлекаете, до необходимого минимума: чем больше данных вы извлекаете, тем дольше будет извлечение.
- Производительность - это баланс между памятью и скоростью. При использовании Core Data в своих приложениях всегда помните об этом балансе.
- example
- Managed object context - это блокнот в памяти для работы с вашими управляемыми объектами.
- Частные фоновые контексты могут использоваться для предотвращения блокировки основного пользовательского интерфейса.
- Контексты связаны с конкретными очередями и должны быть доступны только в этих очередях.
- Дочерние контексты могут упростить архитектуру приложения, упростив сохранение или удаление изменений.
- Управляемые объекты жестко привязаны к своему контексту и не могут использоваться с другими контекстами.
- example
- NSPersistentCloudKitContainer - это мощное дополнение к Core Data для синхронизации нескольких устройств для вашего приложения.
- CloudKit имеет ограничения на модели данных Core Data и не поддерживает напрямую управление версиями моделей Core Data.
- CloudKit Dashboard имеет инструменты проверки схемы и данных, которые помогают отлаживать и поддерживать данные вашего приложения.
- Симуляторы iOS не поддерживают push-уведомления, а это означает, что вам нужно сделать дополнительный шаг, чтобы увидеть автоматические слияния.
- NSPersistentCloudKitContainer просто внедрить в ваш проект, но со временем он может усложнить ваше приложение. Помните об изменениях модели данных на будущее и помните о соображениях производительности.