9 Core Data для Mac и iOS. Извлечение данных

Основные компоненты архитектуры Core Data:
  • Data model—Модель данных. Хранится внутри приложения как ресурс и подгружается в runtime режиме.
  • Persistent store—Сами данные. SQLite библиотека на Mac OS м iOS, но может быть и хранение в памяти или в XML на Mac OS. Можно также создать собственный тип persistent store.
  • Managed Object Context—Создается в runtime режиме из модели данных и persistent store. Приложение может иметь несколько managed object contexts.

Базовые типы архитектур Core Data приложений:
  • Library/shoebox apps—Эти приложения управляют собственнмы Core Data стеком, который более или менее вне поле зрения пользователя. При запуске приложения пользователь получает доступ к этому закулисному хранилищу данных. (Обычно оно расположено в файле в пользовательской Library directory на Mac или в app’s sandbox area на iOS.) Примеры таких приложений: iCal, Address Book, и Bento. В этих приложениях Core Data stack инициализируется в app delegate. Core Data stack должен быть доступен с момента старта приложения.
  • Document-based apps—Эти приложения имеют один или несколько документов которые пользователи могут создавать, открывать, закрывать, и сохранять. Каждый документ имеет собственный Core Data stack—у него своя data model, persistent store, и managed object context. Если несколько документов открываются, каждый имеет собственный managed object context, но они могут работать на одной data model и даже с тем же persistent store. managed object contexts это то что разделяет данные каждого документа.
Т.е. в первом случае БД хранится где-то в пользовательской папке, но она не видна пользователю. А во втором случае БД хранится в видимом пользователю документе который он может например переместить, переименовать, послать другому пользователю и прочее.

Парадигмы извлечения данных:
  • Load-then-process—Время нужное на извлечение данных может играть критическую роль. Основная стратегия это загрузить все релевантные данные в память и получать их по мере надобности. Например: Вы загружаете всю таблицу или текстовый документ в память и потом работаете с ними. С традиционными базами данных загрузка данных может вытекать из действий пользователя которые определяют область необходимых данных например, временной период и так далее.
  • Load-a-chunk—Как часть взаимодействия с пользователем, которое определеяет область данных для загрузки, пользователь может указать такие значения как количество элементов на странице. Пишется код для возвращения порции данных для страницы. Когда пользователь запрашивает другую страницу, данные страницы подгружаются и отображаются. В некоторых случаях время на загрузку одной страницы меньше чем время на загрузку всего набор данных. 
  • Core Data faulting—Core Data реализует faulting. Managed objects могут быть созданы без данных. Такой незаконченный может использоваться без его данных. Только когда данные становятся нужны объект вызывает fault, что побуждает Core Data пойти в persistent store и возвратить данные. Похоже на load-a-chunk, только нет необходимости самому реализовывать pagination и loading, этот сервис предоставляется Core Data. С Core Data’s faulting механизмом, можно писать код так как если бы данные загружались сразу целиком (как в load-then-process парадигме), но фактически данные будут загружаться по запросу.

Core Data эволюционировал из Enterprise Objects Framework в WebObjects в 1994. В этом виде, его архитектура включала adaptors которые позволяли получать доступ к БД: Oracle, Sybase, Informix, и ODBC-compliant servers.

Результат fetch-запроса это массив (NSArray, NSMutableArray) из managed objects. Вместо массива могут быть NSSet, NSMutableSet, NSOrderedSet, NSDictionary, NSMutableDictionary.

managed object context комбинирует persistent store и data model. Это посредник между managed objects и persistent store. Отслеживает что должно быть прочитано или записано.

Для library/shoebox приложений, managed object context обычно находится в app delegate. Для document-based приложений, managed object context есть в каждом документн; это позволяет каждому документу иметь свой собственный Core Data stack.

model и persistent store могут появляться в нескольких документах, но managed object context уникальный для каждого документа.

В старых iOS приложениях и шаблонах managed object context могут храниться во view controller, а не в app delegate. Но по сути это не важно где он находится.

NSPersistentStoreCoordinator *psc = <#Get or create the coordinator#>;
// create the moc
NSManagedObjectContext *myContext = [[NSManagedObjectContext alloc] init];
// set the persistent store
[myContext setPersistentStoreCoordinator:psc];

Имея managed object context можно получить его persistent store:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator;

Имея persistent store coordinator можно получить его managed object model:
- (NSManagedObjectModel *)managedObjectModel;

Создание fetch запроса:
//get the managed object context
NSManagedObjectContext *moc = [self managedObjectContext];
//get the entity description object
NSEntityDescription *entityDescription =
[NSEntityDescription entityForName:@”MyEntityName” inManagedObjectContext:moc];
//create the fetch request
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
//add the entity description
[request setEntity:entityDescription];

С помощью NSEntityDescription можно получить managed object model (имя, атрибуты, свойства и прочее).

Получение результатов запроса происходит вызовом метода executeFetchRequest у managed object context:
- (NSArray *)executeFetchRequest:
(NSFetchRequest *)request
error:(NSError **)error;

Выполнение запроса:
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
// no objects returned — this might or might not be an error
// you may want to check the error result as well
}




Следующий интерфейс демонстрирует как добавляются данные в БД. Тут нужно определиться останавливать ли обновление пока пользователь не предоставит данные или предоставлять пользователю данные по умолчанию, которые он может изменить.
Варианты:

  • Использовать hidden primary key и возможность non-unique user identifier—Хорошей практикой в БД считается использовать name как описательный атрибут для данной записи. unique primary key (генерируется автоматически чтобы обеспечить уникальность) - это фактический идентификатор identifier. Это означает что вы можете иметь non-unique names в вашей БД. Имена меняются для людей, городов, и отсутсвие возможности поменять имя может оказать проблемой.
  • Generate user-visible identifiers to be changed—Можно генерировать имя для новых записей автоматически. Например что-то вроде New Record. Пользователи потом могут использовать возможность модификации для того чтобы изменить имя также как и любое другое значение. С другой стороны имя новой записи (New Record, например) означает что вы имеете non-unique names в пользовательском интерфейсе.
  • Генерация уникальных видимых пользователю идентификаторов которые могут быть изменены—Вы можете автоматически генерировать уникальное имя для новых записей, которое в основном включает в себя timestamp который на любом компьютере будет уникальным. Большинство Core Data приложений сегодня не используют multiuser shared БД, поэтому с одной БЖ каждое timestamp значение будет уникальным.





Нижеследующий пример демонстрирует использование NSPersistentDocument.
Apple’s Departments and Employees sample code
Предоставляются основные команды меню:
Связь между приложением и его документами показана на вкладке Info:




Master-Detail template заменил Navigation-based Application и Split View-based Application templates начиная с Xcode 4.2 и iOS 5. Master-Detail template может универсально использоваться как на iPad так и на iPhone.

iPad

iPhone