Я пишу приложение для iOS, которое использует Core Data для хранения своего материала. Данные хранятся в управляемых объектах и обновляются в отдельных потоках (я использую GCD). В своем Core Data Programming Guide
шаблоне Apple предлагает два способа адаптации Core Data для использования в многопоточной среде:
- Создайте отдельный контекст управляемого объекта для каждого потока и совместно используйте один координатор постоянного хранилища. Это обычно рекомендуемый подход.
- Создайте отдельный контекст управляемого объекта и постоянный координатор хранилища для каждого потока. Этот подход обеспечивает больший параллелизм за счет большей сложности (особенно если вам нужно сообщать об изменениях между разными контекстами) и увеличения использования памяти.
Поэтому я выбрал первое. У меня есть класс Database
, который управляет всеми вещами, связанными с Core Data.
// Database.h
#import <CoreData/CoreData.h>
@interface Database : NSObject
@property (nonatomic, retain, readonly) NSManagedObjectModel *model;
@property (nonatomic, retain, readonly) NSManagedObjectContext *context;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *coordinator;
+ (Database *)sharedInstance;
@end
// Database.m
#import "Database.h"
static NSManagedObjectModel *sharedModel;
static NSPersistentStoreCoordinator *sharedCoordinator;
static NSMutableDictionary *contexts;
@implementation Database
+ (NSMutableDictionary *)contextsDictionary
{
if (!contexts) {
contexts = [[NSMutableDictionary alloc] init];
}
return contexts;
}
+ (NSManagedObjectContext *)contextForThread:(NSThread *)thread
{
id threadKey = @(thread.hash);
NSManagedObjectContext *context = [Database contextsDictionary][threadKey];
if (!context) {
context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = sharedCoordinator;
contexts[threadKey] = context;
[context release];
[[NSNotificationCenter defaultCenter] addObserver:[Database class]
selector:@selector(threadWillExit:)
name:NSThreadWillExitNotification
object:thread];
}
return context;
}
+ (void)threadWillExit:(NSThread *)thread
{
id threadKey = @(thread.hash);
[contexts removeObjectForKey:threadKey];
[[NSNotificationCenter defaultCenter] removeObserver:[Database class]
name:NSThreadWillExitNotification
object:thread];
}
+ (Database *)sharedInstance
{
static Database *shared;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[Database alloc] init];
});
return shared;
}
- (id)init
{
self = [super init];
if (self) {
sharedModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
sharedCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:sharedModel];
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSURL *storeUrl = [NSURL fileURLWithPath:[docsDir stringByAppendingPathComponent: @"MyModelFile"]];
NSError *error = nil;
[sharedCoordinator addPersistentStoreWithType:NSBinaryStoreType
configuration:nil
URL:storeUrl
options:nil
error:&error];
NSAssert(!error, @"Initialization error %@", error);
}
return self;
}
- (NSManagedObjectModel *)model
{
return sharedModel;
}
- (NSPersistentStoreCoordinator *)coordinator
{
return sharedCoordinator;
}
- (NSManagedObjectContext *)context
{
return [Database contextForThread:[NSThread currentThread]];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[sharedModel release];
[sharedCoordinator release];
[contexts release];
[super dealloc];
}
@end
Вот мне и интересно, правильно ли я делаю? Есть ли проблемы в моем коде? Есть ли какие-нибудь шаблоны, которые я могу использовать здесь?
Спасибо.