0

我编写了一个 iOS 应用程序,它使用 Core Data 来存储它的东西。存储在托管对象中并在单独的线程中更新的数据(我正在使用 GCD)。Apple 在其模式中提出了两种方法Core Data Programming Guide来采用 Core Data 在多线程环境中使用:

  1. 为每个线程创建一个单独的托管对象上下文并共享一个持久存储协调器。这是通常推荐的方法。
  2. 为每个线程创建一个单独的托管对象上下文和持久存储协调器。这种方法以更大的复杂性(特别是如果您需要在不同的上下文之间传达更改)和增加的内存使用量为代价提供更大的并发性。

所以我选择了第一个。我有一个Database类来管理所有与核心数据相关的东西。

// 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

所以我很好奇,我做得对吗?我的代码有问题吗?我可以在这里使用任何模式吗?

谢谢。

4

1 回答 1

0

所描述的多线程模式现在不相关,因为核心数据具有内置的并发支持。正如OS X v10.7 和 iOS 5.0 的核心数据发行说明通用背景实践文章中提到的那样,可以使用适当的并发类型来配置 mocNSPrivateQueueConcurrencyTypeNSMainQueueConcurrencyType. performBlock然后可以在传递给或方法的块中执行每个具有托管对象上下文的操作,performBlockAndWait并让核心数据内部处理所有并发内容。

于 2014-03-22T06:55:11.677 回答