Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/106.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有多个并行数据库访问的iOS应用程序设计_Ios_Core Data_Grand Central Dispatch_Nsmanagedobjectcontext - Fatal编程技术网

具有多个并行数据库访问的iOS应用程序设计

具有多个并行数据库访问的iOS应用程序设计,ios,core-data,grand-central-dispatch,nsmanagedobjectcontext,Ios,Core Data,Grand Central Dispatch,Nsmanagedobjectcontext,在我的应用程序中,我获取带有JSON内容的请求,解析它们并将它们存储在CoreData中。同时,用户与数据库交互(读写访问) 将数据存储到数据库后,将启动第二个任务,根据接收到的数据创建新数据。我将使用GrandCentralDispatch进行解析,并将数据存储到数据库中 我的问题是,当使用GCD时,我得到了一个EXC\u BAD\u ACCESS,这可能是由于我假设的核心数据的非线程安全性造成的。另一个错误是在使用contextperformBlockAndWait时出现死锁 我应该如何设计

在我的应用程序中,我获取带有JSON内容的请求,解析它们并将它们存储在CoreData中。同时,用户与数据库交互(读写访问)

将数据存储到数据库后,将启动第二个任务,根据接收到的数据创建新数据。我将使用GrandCentralDispatch进行解析,并将数据存储到数据库中

我的问题是,当使用GCD时,我得到了一个
EXC\u BAD\u ACCESS
,这可能是由于我假设的核心数据的非线程安全性造成的。另一个错误是在使用context
performBlockAndWait
时出现死锁

我应该如何设计能够正确处理GCD和
NSMutableContexts
的应用程序

-------编辑--------

既然我已经阅读了核心数据编程指南,我就必须使用线程限制模式

我的应用程序目前的结构是这样的:我有几个经理,每个经理都有自己的背景。但是当使用多个线程时,我会发现3个线程调用同一个管理器,这意味着3个线程同时使用一个上下文。这将导致死锁

为了解决这个问题,我想到了通过threadname创建一个上下文,如下所示:

- (NSManagedObjectContext *)createManagedObjectContextWithTreadName:(NSString*) threadname {

    if([NSThread currentThread].name.length ==0){
        [NSThread currentThread].name = threadname; 
    }

    NSManagedObjectContext *context = nil;
    context = [self.contextStore objectForKey:threadname];

    if(!context){
        NSLog(@"Creating context for threadname: %@",threadname);

        NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator;
        if (coordinator != nil)
        {
            context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
            context.persistentStoreCoordinator = coordinator;
            context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;

            NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
            [nc addObserver:self selector:@selector(mergeChangesFromMOC:) name:NSManagedObjectContextDidSaveNotification object:context];
            [self.contextStore setValue:context forKey:threadname];
        }
    }
    return context;
}

这是一个好主意吗?

从阅读开始。

从阅读开始。

好的-以下是我解决问题的方法:

+(NSManagedObjectContext *)managedObjectContext {
    AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    NSManagedObjectContext *moc = delegate.managedObjectContext;

    NSThread *thread = [NSThread currentThread];

    if ([thread isMainThread]) {
        return moc;
    }

    // a key to cache the context for the given thread
    NSString *threadKey = [NSString stringWithFormat:@"%p", thread];

    // delegate.managedObjectContexts is a mutable dictionary in the app delegate
    NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts;

    if ( [managedObjectContexts objectForKey:threadKey] == nil ) {
        // create a context for this thread
        NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

        threadContext.persistentStoreCoordinator = [moc persistentStoreCoordinator];
        threadContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;

        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc addObserver:self selector:@selector(mergeChangesFromMOC:) name:NSManagedObjectContextDidSaveNotification object:threadContext];

        // cache the context for this thread
        [managedObjectContexts setObject:threadContext forKey:threadKey];
        //NSLog(@"MocCount: %d",managedObjectContexts.count);
    }

    return [managedObjectContexts objectForKey:threadKey];
}

+ (void)mergeChangesFromMOC:(NSNotification *)aNotification {

    //NSLog(@"Performing a merge of managed object context in class %@",[self class]);

    @try {
        AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
        NSManagedObjectContext *moc = delegate.managedObjectContext;
        [moc mergeChangesFromContextDidSaveNotification:aNotification];


        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:[aNotification object]];      
    }
    @catch (NSException * e) {
        NSLog(@"Stopping on exception: %@", [e description]);
    }
    @finally {}
}

在任何需要上下文的地方,我都会询问[ContainingClass managedObjectContext],并获取主线程或我所在线程的上下文。当需要合并时,这将在主线程上执行。

确定-以下是我如何解决它的:

+(NSManagedObjectContext *)managedObjectContext {
    AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    NSManagedObjectContext *moc = delegate.managedObjectContext;

    NSThread *thread = [NSThread currentThread];

    if ([thread isMainThread]) {
        return moc;
    }

    // a key to cache the context for the given thread
    NSString *threadKey = [NSString stringWithFormat:@"%p", thread];

    // delegate.managedObjectContexts is a mutable dictionary in the app delegate
    NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts;

    if ( [managedObjectContexts objectForKey:threadKey] == nil ) {
        // create a context for this thread
        NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

        threadContext.persistentStoreCoordinator = [moc persistentStoreCoordinator];
        threadContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;

        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc addObserver:self selector:@selector(mergeChangesFromMOC:) name:NSManagedObjectContextDidSaveNotification object:threadContext];

        // cache the context for this thread
        [managedObjectContexts setObject:threadContext forKey:threadKey];
        //NSLog(@"MocCount: %d",managedObjectContexts.count);
    }

    return [managedObjectContexts objectForKey:threadKey];
}

+ (void)mergeChangesFromMOC:(NSNotification *)aNotification {

    //NSLog(@"Performing a merge of managed object context in class %@",[self class]);

    @try {
        AppDelegate *delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
        NSManagedObjectContext *moc = delegate.managedObjectContext;
        [moc mergeChangesFromContextDidSaveNotification:aNotification];


        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:[aNotification object]];      
    }
    @catch (NSException * e) {
        NSLog(@"Stopping on exception: %@", [e description]);
    }
    @finally {}
}

在任何需要上下文的地方,我都会询问[ContainingClass managedObjectContext],并获取主线程或我所在线程的上下文。当需要合并时,这将在主线程上执行。

只是一个问题,如何删除不再活动的线程的上下文?只是一个问题,如何删除不再活动的线程的上下文?