Чтение онлайн

ЖАНРЫ

iOS. Приемы программирования

Нахавандипур Вандад

Шрифт:

#import <CoreData/CoreData.h>

@class Manager;

@interface Employee: NSManagedObject

@property (nonatomic, retain) NSNumber * age;

@property (nonatomic, retain) NSString * firstName;

@property (nonatomic, retain) NSString * lastName;

@property (nonatomic, retain) Manager *manager;

@end

Как видите, в этом файле появилось новое свойство. Оно называется manager и относится к типу Manager. Таким образом, начиная с данного момента

мы при наличии ссылки на конкретный объект типа Employee можем получить доступ к свойству manager, а через него — к объекту Manager данного конкретного сотрудника (если менеджер есть). Рассмотрим. h-файл сущности Manager:

#import <Foundation/Foundation.h>

#import <CoreData/CoreData.h>

@class Employee;

@interface Manager: NSManagedObject

@property (nonatomic, retain) NSNumber * age;

@property (nonatomic, retain) NSString * firstName;

@property (nonatomic, retain) NSString * lastName;

@property (nonatomic, retain) NSSet *employees;

@end

@interface Manager (CoreDataGeneratedAccessors)

— (void)addFKManagerToEmployeesObject:(Employee *)value;

— (void)removeFKManagerToEmployeesObject:(Employee *)value;

— (void)addFKManagerToEmployees:(NSSet *)values;

— (void)removeFKManagerToEmployees:(NSSet *)values;

@end

Для сущности Manager также создается свойство employees. Тип данных этого объекта — NSSet. Это означает, что свойство employees любого экземпляра сущности Manager может содержать от 1 до N сущностей Employee. В этом и заключается принцип отношения «один ко многим»: один менеджер, несколько сотрудников.

Другой тип отношений, которые, возможно, потребуется реализовать, называется «многие ко многим». По сравнению с отношением Manager к Employee при отношении «многие ко многим» один менеджер может иметь N сотрудников, а каждый сотрудник может подчиняться N менеджерам. Чтобы организовать такие отношения, выполните те же инструкции, что и при создании отношения «один ко многим», но выделите сущность Employee, а потом отношение manager. Измените это название на managers и установите флажок To-Many Relationship (Отношение ко многим) (рис. 16.19). Теперь стрелка будет заострена с обоих концов.

Рис. 16.19. Создание отношения «многие ко многим» между сущностями Manager и Employee

Теперь, открыв файл Employee.h, вы увидите, что его содержимое изменилось:

#import <Foundation/Foundation.h>

#import <CoreData/CoreData.h>

@class Manager;

@interface Employee: NSManagedObject

@property (nonatomic, retain) NSNumber * age;

@property (nonatomic, retain) NSString * firstName;

@property (nonatomic, retain) NSString * lastName;

@property (nonatomic, retain) NSSet *managers;

@end

@interface Employee (CoreDataGeneratedAccessors)

— (void)addManagersObject:(Manager *)value;

— (void)removeManagersObject:(Manager *)value;

— (void)addManagers:(NSSet *)values;

— (void)removeManagers:(NSSet *)values;

@end

Как

видите, свойство managers сущности Person теперь представляет собой множество. Поскольку отношение сотрудника к его менеджерам — это множество и такое же отношение существует между менеджером и сотрудниками, здесь мы имеем пример отношения «многие ко многим»

В коде, написанном для отношения «один ко многим», можно просто создать новый управляемый объект Manager (о том, как вставлять объекты в контекст управляемых объектов, рассказано в разделе 16.3), сохранить его в контексте управляемых объектов, а потом соединить с парой управляемых объектов Employee — и их тоже сохранить в контексте. Теперь, чтобы ассоциировать менеджера с сотрудником, задайте в качестве значения для свойства FKEmployeeToManager, относящегося к экземпляру Employee, экземпляр управляемого объекта Manager. После этого фреймворк Core Data сам создаст необходимое отношение.

Если потребуется получить всех сотрудников (типа Employee), ассоциированных с объектом-менеджером (типа Manager), нужно будет просто воспользоваться методом экземпляра allObjects, относящимся к свойству FKManagerToEmployees вашего объекта-менеджера. Это объект типа NSSet, поэтому можно применить метод экземпляра allObjects, чтобы получить массив всех объектов-сотрудников, ассоциированных с конкретным объектом-менеджером.

16.9. Выборка данных в фоновом режиме

Постановка задачи

Требуется выполнять операции выборки данных в стеке Core Data, причем только в фоновом режиме. Это отличная возможность создать по-настоящему отзывчивый пользовательский интерфейс.

Решение

Перед тем как заниматься выборкой данных в фоновом режиме, создайте новый контекст управляемых объектов с параллелизмом типа NSPrivateQueueConcurrencyType. Затем воспользуйтесь методом performBlock: нового фонового контекста для выборки данных в фоновом режиме. Как только это будет сделано и вы будете готовы использовать выбранные объекты в пользовательском интерфейсе, вернитесь в поток пользовательского интерфейса с помощью dispatch_async (см. раздел 7.4). Далее для каждого объекта, выбранного в фоновом режиме, выполните в основном контексте метод objectWithID:. Так объекты, выбранные в фоновом режиме, будут перенесены в ваш приоритетный контекст, где вы сможете оперировать ими в потоке пользовательского интерфейса.

Обсуждение

Выборка объектов в основном потоке — не самая хорошая идея. Выполнять ее в главном потоке можно лишь в случаях, когда в стеке Core Data совсем немного элементов. Дело в том, что при операции выборки в Core Data обычно выполняется поисковый вызов. Затем этот вызов должен выбрать для вас определенные данные, обычно с помощью предиката. Чтобы сделать пользовательский интерфейс более отзывчивым, лучше всего выполнять такие операции выборки в фоновом контексте.

Вы можете создать в приложении столько контекстов, сколько захотите, однако помните об одном железном правиле. Нельзя передавать управляемые объекты между контекстами в разных потоках, так как объекты не являются потокобезопасными. Таким образом, если вы выбираете объекты в фоновом контексте, то не можете использовать их в главном потоке. Вот как следует передавать управляемые объекты между потоками: объект выбирается в фоновом потоке, а потом переносится в главный контекст (контекст, работающий в основном потоке). Это делается с помощью метода objectWithID: главного контекста. Этот метод принимает объект типа NSManagedObjectID. Поэтому в фоновом потоке мы на самом деле не выбираем управляемые объекты как таковые, а лишь берем их сохраняемые ID, после чего передаем эти ID главному контексту, который сам получает для вас управляемый объект. Итак, вы выполняете в фоновом режиме и поиск, и выборку объектов, затем передаете ID найденных объектов главному контексту. Получением самих объектов занимается уже главный контекст. Если действовать таким образом, главный контекст будет располагать сохраняемыми ID объектов, а получение этих объектов из постоянного хранилища в такой ситуации протекает гораздо быстрее, чем при выполнении полномасштабного поиска в главном контексте.

Поделиться с друзьями: