Pull to refresh

Использование ActiveRecord для работы с Core Data

Reading time4 min
Views6.5K
Введение


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 и добавляем ее к проекту:



Добавляем в 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];
Tags:
Hubs:
+24
Comments14

Articles