Разработка iPhone/iPod touch приложений: CoreData. Что в имени твоем? (Часть 1) – Основные понятия

Объект – CoreData.
Задача – изучение параметров и возможностей.
Результат – получение общих понятий о возможностях и возможных применениях.

Итак. CoreData – что за зверь такой? Как говорит нам документация, это очень хороший и пушистый зверь, который всего лишь является надстройкой над конкретным хранилищем данных. а именно – над данными, которые хранятся в бинарном виде(CoreData-формат), XML, SQLite базе.

Что же все-таки позволяет сделать CoreData? Операции со сложными графами объектов, с множественными связями, валидацией, с возможностью осуществлять undo/redo операции на и… сохранять эти графы в некотором хранилище данных. Что получает от этого программист? Возможность не опускаться до уровня отщепенцев базы данных, не рассматривать проблему сериализации/десериализации, работая на уровне объектов.

Необходимо заметить, что CoreData справляется с этими задачами очень шустро, и не идет ни в какое сравнение по скорости и количеству кода с другими реализациями ORM под iPhone (будь то самописный ORM на основе SQLite, либо надстрока FMDB, либо SQLite Persistence Objects).

Кроме всего прочего, в SDK 3.0 появились специальные вспомогательные классы, позволяющие быстро интегрировать ввод/вывод данных, сохраненных с помощью CoreData. Так, при помощи NSFetchedResultsController можно без особых проблем использовать UITableView для отображения нескольких ТЫСЯЧ объектов.
Интересно? Читаем дальше …

Четыре слона CoreData

CoreData, как и многие другие объекты нашего плоского мира покоится на четырех слонах, которых обычно называют стеком CoreData (CoreData Stack). Разработчики из Apple дали им следующие имена:

  • ManagedObjectContext
  • ManagedObjectModel
  • PersistentStoreCoordinator
  • PersistentStore

Рассмотрим, за что отвечает каждый из них.

PersistentStore

PersistentStore

PersistentStore

Этот слон PersistenceStore отвечает за то, в каком виде хранятся объекты , и где они хранятся. CoreData умеет работать с четырьмя видами хранилищ – XML, SQLite, Binary и inMemory. Правда, XML-хранилище в iPhone SDK 3.0 отсутствует, так что, можно считать что с тремя. PersistenceStore не представлен никаким классом в iPhone SDK 3.0, соответственно не настраивается, и выбирается PersistenceStoreCoordinator’ом.

 

PersistentStoreCoordinator

PersistentStoreCoordinator дает возможность использовать одновременно несколько хранилищ объектов(PersistentStore). Мне, честно говоря, сложно сказать, в каком случае это может понадобиться, но факт остается фактом. Инициализируется он с помощью следующего вызова:


// Cоздаем SQLite Persistent Store
NSError *error;
NSURL * = [NSURL fileURLWithPath:[self applicationDocumentsDirectory]
          stringByAppendingPathComponent:@"MyDataBaseName.sqlite"]];
NSPersistentStoreCoordinator * persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
          initWithManagedObjectModel: managedObjectModel];
if (![persistentStoreCoordinator
         addPersistentStoreWithType:NSSQLiteStoreType
         configuration:nil URL:storeUrl options:nil error:&error]) {
  // Handle error
}

В коде можно наблюдать переменную managedObjectModel, о которой сейчас и пойдет речь.

managedobjectmodel

Managed Object Model

ManagedObjectModel

В библиотеке CoreData представлена Managed Object Model классом NSManagedObjectModel. Судя по названию эта слониха модель есть ни что иное как схема базы данных(если бы мы работали с БД, конечно). То есть хранит информацию о всех сущностях, о их связях, зависимостях, свойствах, запросах. Для упрощения создания такой модели, в Xcode присутствует специальный редактор(на картинке справа). Файлы моделей в проекте имеют расширение .xcdatamodel, и затем компилируются в .mom файлы, уже из которых можно инициализировать NSManagedObjectModel. В коде все выглядит намного проще:


// Инициируем модель из главного Bundle'а
// mergedModelFromBundles - загрузит все .mom файлы, и попытается содать из них одну общую
// модель. Обычно такой файл один, и проблем не возникает ;)
// Бывают,конечно, исключения. Но сейчас речь не о них.
NSManagedObjectModel * managedObjectModel =
   [[NSManagedObjectModel mergedModelFromBundles:nil] retain];   

// Создали и забыли. Обычно MOM используется всего один раз в программе - при добавлении
// PersistenceStoreCoordinator'a

В результате выполнения кода создастся MOM, которая объединит все файлы моделей(один;), которые будут найдены  в текущем bundle. А в редакторе MOM может выглядеть следующим образом:

Пример Managed Object Model

Пример Managed Object Model

После создания MOM, пора приниматься за создание объектов, которыми можно оперировать в приложении.

 

Managed Object

Managed Object – это объекты, которыми оперирует CoreData. Для удобства можно представить, что это те же самые NSObject – особой разницы не будет. Классы-Entity можно очень быстро сгенерировать из все того же редактора модели. Для этого надо открыть редактор модели, и, нажав Command-N выбрать “Managed Object Class”.

Генерация классов модели

Генерация классов модели

Выбираем классы, которые необходимы – и – готовые Классы-сущности уже в проекте. Все необходимые методы для работы со связями уже реализованы. Вот так, например, выглядит класс Body после генерации. Сразу обращаем внимание на методы доступа к связям, и на то что связи один ко многим представлены не в виде NSArray, а в виде NSSet.


#import <CoreData/CoreData.h>

@class Arm;
@class Head;
@class Leg;
@class Head;

@interface Body :  NSManagedObject
{
}

@property (nonatomic, retain) NSSet* arms;
@property (nonatomic, retain) Head * head;
@property (nonatomic, retain) NSSet* legs;

@end

@interface Body (CoreDataGeneratedAccessors)
- (void)addArmsObject:(Arm *)value;
- (void)removeArmsObject:(Arm *)value;
- (void)addArms:(NSSet *)value;
- (void)removeArms:(NSSet *)value;

- (void)addLegsObject:(Leg *)value;
- (void)removeLegsObject:(Leg *)value;
- (void)addLegs:(NSSet *)value;
- (void)removeLegs:(NSSet *)value;

@end

С моделью, наконец-то, закончили. Остался еще один слон класс – NSManagedObjectContext

Managed Object Context

Managed Object Context

Managed Object Context

С этим слоном классом с одной стороны проще, с другой стороны – писать о нем нужно много, и подробно, так как с ним прийдется мучаться встречаться в процессе написания кода чаще всего (не считая NSFetchedRequest). Если проводить аналогии с БД, то Managed Object Context (MOC) – это транзакция. Если не принимать во внимание undoManager, то на этом сравнение можно и закончить. То есть, все объекты попадают в хранилище (БД) и из него, только через MOC. Контекстов можно создавать несколько, и каждый привязан к PersistenceStoreCoordinator’у, и знает куда сохранять и, соответственно, откуда загружать данные.  Зачем могут понадобиться несколько MOC’ов?  Как вариант – для независимого изменения и последующего сохранения классов-сущностей в хранилище.

Создается MOC очень просто:


NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
 if (coordinator != nil) {
    managedObjectContext = [[NSManagedObjectContext alloc] init];
    [managedObjectContext setPersistentStoreCoordinator: coordinator];
 }

Все. Ознакомление с основными понятиями CoreData можно считать законченым. Надеюсь, что прочитавшие статью теперь не будут больше бояться длинных названий вроде NSManagedObjectContext, NSManagedObjectModel, NSPersistenceCoordinator, и смогут представить за что они отвечают в CoreData. Про работу с NSManagedObjectContext, NSFetchedRequest и другими прелестями CoreData – я напишу отдельно.

Комментарии

olgerd

в 23:37, 22.09.2009

grand merci! ;)

…жду продолжения!

Makarov Alexey

в 9:04, 21.01.2010

А что делать если нужны предопределенная заполненная default-значениями база. Как ее заполнять? Можете ссылку дать, где можно почитать об этом.

Kilew

в 11:51, 21.01.2010

>А что делать если нужны предопределенная заполненная default-значениями база. Как ее заполнять? Можете ссылку дать, где можно почитать об этом.

В общем мы делали так:
1) Создаем АПП-1, забиваем базу нужными значениями, ложим ее в ресурсы АППа-2
2) АПП-2 (главный) первым делом проверяет, есть ли в папке Documents созданная база. Если нету, то копирует из ресурсов.
3) Апп-2 Всегда работает с базой из папки Documents.

[...] в основных понятиях Core Data, можно начинать им пользоваться. Для простоты и [...]

Оставить комментарий