Введение
Active Record — это паттерн проектирования приложений, использующих для хранения информации базу данных. Таблица базы данных отображается в виде класса приложения, а отображением объекта класса является строка таблицы. Интерфейс такого объекта должен содержать такие функции, как Insert, Update и Delete плюс свойства, которые отвечают столбцам таблицы. При создании объекта в таблицу добавляется новая строка, когда происходит обновление объекта, соответствующая строка в таблице так же обновляется.
Core Data и Active Record
Core Data основана на паттерне Active Record, но для работы с базой данных приходится писать довольно громоздкий код. Например, вот пример Apple:
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
// Set example predicate and sort orderings...
NSNumber *minimumSalary = ...;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(lastName LIKE[c] 'Worsley') AND (salary > %@)", minimumSalary];
[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
NSError *error;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}
Как видно из примера для поиска в базе данных Сотрудников(Employee) у которых фамилия содержит «Worsley» и зарплата выше минимальной зарплаты приходится писать много «лишнего» кода.
Решение данной проблемы предоставили Magical Panda в своей библиотеке ActiveRecord for Core Data
Вот тот же пример, только с использованием ActiveRecord for Core Data:
NSNumber *minimumSalary = ...;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(lastName LIKE[c] 'Worsley') AND (salary > %@)", minimumSalary];
NSArray *employees = [Employee findAllSortedBy:@"firstName" asceding:YES withPredicate:predicate];
ActiveRecord for Core Data позволяет:
1. Сделать чище код по работе с Core Data
2. Позволяет делать простые однострочные запросы
3. Несмотря на простоту, позволяет модифицировать NSFetchRequest, когда запрос нуждается в модификации.
Использование ActiveRecord for Core Data
Настройка
Скачиваем библиотеку ActiveRecord for Core Data и добавляем ее к проекту:
![](https://habrastorage.org/storage1/fe32c465/78cb5b7d/514ea867/e91c79f0.png)
Добавляем в MyProjectName-Prefix.pch
#import "CoreData+ActiveRecordFetching.h"
в AppDelegate в application:didFinishLaunchingWithOptions: добавлям вызов
[ActiveRecordHelpers setupCoreDataStackWithAutoMigratingSqliteStoreNamed:@"MyProject.sqlite"];
Данный метод создаст NSPersistentStore с указанным именем и файлом модели .xcdatamodeld который найдет в бандле приложения.
Default Managed Object Context
При работе с Core Data используется объект NSManagedObjectContext. ActiveRecord for Core Data позволяет установить DefaultContext, который будет NSManagedObjectContext по-умолчанию для всего приложения. Создание NSManagedObjectContext для использования в других потоках выглядит следующим образом:
NSManagedObjectContext *myNewContext = [NSManagedObjectContext newContext];
Этот контекст можно сделать по-умолчанию, и тогда он будет использоваться во всех запросах, если в названии метода запроса вконце не стоит «inContext:». Рекомендуется создавать и устанавливать контекст по-умолчанию только в главном потоке.
Выборка данных
Допустим есть класс Song с полями id, length и name:
@interface Song : NSManagedObject
@property (nonatomic, retain) NSNumber * length;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * id;
@end
#import "Song.h"
@implementation Song
@dynamic length;
@dynamic name;
@dynamic id;
@end
В библиотеке ActiveRecord for Core Data содержится категория «NSManagedObject+ActiveRecord.h», тоесть все наследники NSManagedObject будут отвечать на сообщения ActiveRecord for Core Data.
Большенство методов в ActiveRecord for Core Data возвращают массив результатов. Например если необходимо найти все Song объекты в базе данных, то вызов будет иметь следующий вид:
NSArray *songs = [Song findAll];
Поиск песен, отсортированных по name будет иметь вид:
NSArray *songsSorted = [Song findAllSortedByProperty:@"name" ascending:YES];
Если есть песня с уникальным значением атрибута, то можно воспользоваться функцией:
Song *song = [Song findFirstByAttribute:@"name" withValue:@"Imagine"];
Так же ActiveRecord for Core Data позволяет использовать NSPredicate:
NSPredicate *songFilter = [NSPredicate predicateWithFormat:@«length > %@», ...];
NSArray *songs = [Song findAllWithPredicate:peopleFilter];
Редактирование данных
Создать запись в базе данных при помощи ActiveRecord for Core Data очень просто:
Song *song = [Song createEntity];
Удаление:
[song deleteEntity];
Редактирование аттрибутов:
Song *song = [Song createEntity];
song.name = "stairway to heaven";
song.length = [NSNumber numberWithInt:150];
После редактирования данных необходимо сохранить контекст:
[[NSManagedObjectContext defaultContext] save];