Вы находитесь на странице: 1из 22

Сегодня

Core Data
Core Data Demo
Базы Данных
База данных — совокупность данных,
хранимых в соответствии со схемой данных

База данных — совместно используемый набор


логически связанных данных (и описание этих
данных)

База данных — совокупность данных,


организованных в соответствии с концептуальной
структурой, описывающей характеристики этих
данных и взаимоотношения между ними
Базы Данных - Классификация по модели
данных

• Иерархическая
• Объектная и объектно-ориентированная
• Объектно-реляционная
• Реляционная
• Сетевая
• Функциональная.
Базы Данных
Объектно-ориентированная база данных (ООБД) — база данных, в которой данные
моделируются в виде объектов, их атрибутов, методов и классов.

Некоторые объектно-ориентированные базы данных разработаны для плотного


взаимодействия с такими объектно-ориентированными языками
программирования как Python, Java, C#, Visual Basic .NET, C++, Objective-C и
Smalltalk; другие имеют свои собственные языки программирования.
Core Data
Объектно-ориентированная база данных

Очень, очень мощный и огромный framework в iOS


(мы будем разбирать только основы)

Это способ создания графа объектов,


поддерживаемого базой данных, основаной на XML,
binary, или SQLite хранилище

Core Data напрямую взаимодействует с SQLite,


изолируя разработчика от базового SQL
Небольшое введение
Core Data
Мы будем работать с Entities, Attributes и Relationships

Как вы получаете доступ ко всему этому в своем коде?

Вам нужен NSManagedObjectContext.

Это центр, вокруг которого строится работа с Core Data


Core Data
Как получить контекст?

Вы получаете один из NSPersistentContainer

Специальный код добавляется в AppDelegate(Если указывали Use Core Data при


создании проекта)

Вы можете получить доступ к этому свойству в AppDelegate вот так


(UIApplication.shared.delegate as! AppDelegate).persistentContainer

Мы получаем контекст, который нам нужен из persistentContainer, используя его


свойство viewContext.

Это возвращает NSManagedObjectContext подходящий только для использования в


основной очереди (main queue).

let container =
(UIApplication.shared.delegate as! AppDelegate).persistentContainer

let context: NSManagedObjectContext = container.viewContext


Core Data
немного улучшений для
(UIApplication.shared.delegate as! AppDelegate).persistentContainer

иногда создаем статический вариант для быстрого доступа


static var persistentContainer: NSPersistentContainer {
return (UIApplication.shared.delegate as!
AppDelegate).persistentContainer
}

тогда можно получить доступ к контейнеру намного короче

let coreDataContainer = AppDelegate.persistentContainer


Core Data
После получения контекста NSManagedObjectContext мы можем добавлять и
удалять entity из базы данных
let context = AppDelegate.viewContext
let job: NSManagedObject =
NSEntityDescription.insertNewObject(forEntityName: "Job",
into: context)

Метод класса NSEntityDescription возвращает экземпляр NSManagedObject.

Все объекты в базе данных представлены NSManagedObjects или их подклассами.

Теперь необходимо NSManagedObjects установить значения, которые будет хранить


Core Data
Мы получаем возможность работать с свойствами NSManageObject обьекта
используя методы из протокола NSKeyValueCoding
func value(forKey: String) -> Any? {}
func setValue(Any?, forKey: String) {}

value(forKeyPath:)/setValue(_,forKeyPath:)
let username = job.value(forKeyPath: "user.name") as? String

где Key - это точное название вашего атрибута


Core Data
Все изменения, которые вы сделали применяются только в оперативной
памяти, что бы сохранить ваши данные необходимо вызвать save

do {
try context.save()
} catch {
// используйте переменную по умолчанию error что бы получить
информацию об ошибке
}

Каждый раз когда вы делаете изменения в базе, вам необходимо ее сохранить.

Старайтесь вызывать одно сохранение для нескольких изменений, это приведет к


приросту производительности
Core Data
что бы не работать с

func value(forKey: String) -> Any? {}


func setValue(Any?, forKey: String) {}

а использовать привычные var, мы делаем наследника от NSManageObject

Подкласс будет иметь vars для каждого атрибута в базе данных.


Мы называем наш подкласс тем же именем, что и Entity, которому оно соответствует.
Xcode генерирует нам дополнительные файлы.
Небольшое демо
Core Data
Работа с entity используя подклассы автоматически добавляет(связывает)
let job = Job(context: context) задание к пользователю Коля
job.identifier = 123123
job.title = "Пылесосит"
job.selected = true
job.created = Date() as NSDate
job.user = User(context: job.managedObjectContext!)
job.user?.name = "Kolya"

У пользователя появляется задание, которое можно получить примерно так


if let joesJobs = job.user.jobs as? Set<Job> {}

каждый NSManageObject знает в


каком контексте он находится
Core Data
Используйте галочку Use Scalar Type для чисел, что бы они стали нормальными
Swift типами, а не остались NSNumber

Удаление из базы
context.delete(job)
• после удаления все взаимосвязи данного объекта в базе будут обновлены
• обращайте внимание на правила удаления для обьектов
• func prepareForDeletion() - метод, который вызывается в подклассе
NSManageObject перед удалением, если у вас есть переменные которые
содержат количество заданий(job), то можно сделать -= 1 для них
Core Data
Запросы к базе мы делаем с помощью NSFetchRequest. Для этого нам
понадобиться:
• Entity - обязательно
• NSSortDescriptor - как будет отсортирован массив
• NSPredicate - как будет отфильтрован массив
Указывать обязательно так как
Swift не может определить тип

let request: NSFetchRequest<Job> = Job.fetchRequest()


let sortDescriptor = NSSortDescriptor(
key: "text", ascending: true,
selector: #selector(NSString.localizedStandardCompare(_:)))// н
request.sortDescriptors = [sortDescriptor]
request.predicate = NSPredicate(format: "text contains[c] %@", searchString)
Core Data
let request: NSFetchRequest<Job> = Job.fetchRequest()
request.predicate = NSPredicate(format: "identifier = %d",
task.identifier)

do {
let matches = try context.fetch(request)
} catch {
throw error
}

Массив ([Job]) всех объектов из базы


данных с данным идентификатором
или пустой массив, если ничего не
найдено
Core Data

Учтите, что данные не извлекаются из базы пока вы к


ним не обратитесь, это может привести к тому, что
вы не увидите значения полей обьектом в дебагере,
пока не обратитесь к ним напрямую.
Core Data
NSManagedObjectContext - не потоко безопасен

К счастью, доступ к Core Data обычно очень быстрый, поэтому многопоточность
требуется редко.
NSManagedObjectContexts создаются с использованием модели параллелизма на
основе очереди (queue-based concurrency model).
Это означает, что вы можете работать только с контекстом из очереди, в которой
он был создан. Часто мы используем только основную очередь и контейнер из
AppDelegate и его viewContext, поэтому это не проблема

Потоко-безопасная работа с контекстом


context.perform {
все находящееся здесь выполнится на

} безопасной очереди, на очереди в которой
контекст был создан

Если ваше приложение не содержит многопоточности, то можно не делать этого, в


остальных случая желательно оборачивать всю работу с CoreData в такие блоки
Core Data
Большое ДЕМО

Вам также может понравиться