Ios 核心数据后台处理,保存不推送到主上下文

Ios 核心数据后台处理,保存不推送到主上下文,ios,multithreading,cocoa-touch,core-data,save,Ios,Multithreading,Cocoa Touch,Core Data,Save,我正在体验一些核心数据后台处理的问题。当我在后台上下文中保存时,它似乎不会将保存推到主上下文。调试代码时,我注意到正在执行save操作的后台线程似乎已停止(?)此行为导致我获取过时的对象 Stacktrace from save: Thread 29, Queue : NSManagedObjectContext Queue #0 0x9a5cf80e in semaphore_wait_trap () #1 0x02216f08 in _dispatch_thread_semaphore_

我正在体验一些核心数据后台处理的问题。当我在后台上下文中保存时,它似乎不会将保存推到主上下文。调试代码时,我注意到正在执行save操作的后台线程似乎已停止(?)此行为导致我获取过时的对象

Stacktrace from save:

Thread 29, Queue : NSManagedObjectContext Queue
#0  0x9a5cf80e in semaphore_wait_trap ()
#1  0x02216f08 in _dispatch_thread_semaphore_wait ()
#2  0x02214b3a in _dispatch_barrier_sync_f_slow ()
#3  0x02214a5c in dispatch_barrier_sync_f ()
#4  0x01dfe03b in _perform ()
#5  0x01dfde9e in -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] ()
#6  0x01ddb33c in -[NSManagedObjectContext save:] ()
#7  0x00096213 in __45-[CoreDataHelper saveInManagedObjectContext:]_block_invoke_0 at /Users/peterwarbo/Documents/Projects/MessagePlanr/MessagePlanr/CoreDataHelper.m:307
#8  0x01e734b3 in developerSubmittedBlockToNSManagedObjectContextPerform_privateasync ()
- (void)saveInManagedObjectContext:(NSManagedObjectContext *)context {

    if (context == nil) {

        // Use default MOC
        context = self.managedObjectContext;

        NSError *error = nil;

        if (context != nil)
        {
            if ([context hasChanges] && ![context save:&error])
            {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 */
                DLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }

    } else {

        // First save (child) context
        [context performBlock:^{

            NSError *error = nil;

            if ([context hasChanges] && ![context save:&error])
            {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 */
                DLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }];


        // Then save parent context
        [self.managedObjectContext performBlock:^{

            NSError *error = nil;

            if ([self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error]) {

                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 */
                DLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }];
    }
}
- (NSManagedObjectContext *)threadedManagedObjectContext {

    NSManagedObjectContext *threadedMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    threadedMoc.parentContext = self.managedObjectContext; //self.managedObjectContext is of type NSMainQueueConcurrencyType

    return threadedMoc;
}
保存方法:

Thread 29, Queue : NSManagedObjectContext Queue
#0  0x9a5cf80e in semaphore_wait_trap ()
#1  0x02216f08 in _dispatch_thread_semaphore_wait ()
#2  0x02214b3a in _dispatch_barrier_sync_f_slow ()
#3  0x02214a5c in dispatch_barrier_sync_f ()
#4  0x01dfe03b in _perform ()
#5  0x01dfde9e in -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] ()
#6  0x01ddb33c in -[NSManagedObjectContext save:] ()
#7  0x00096213 in __45-[CoreDataHelper saveInManagedObjectContext:]_block_invoke_0 at /Users/peterwarbo/Documents/Projects/MessagePlanr/MessagePlanr/CoreDataHelper.m:307
#8  0x01e734b3 in developerSubmittedBlockToNSManagedObjectContextPerform_privateasync ()
- (void)saveInManagedObjectContext:(NSManagedObjectContext *)context {

    if (context == nil) {

        // Use default MOC
        context = self.managedObjectContext;

        NSError *error = nil;

        if (context != nil)
        {
            if ([context hasChanges] && ![context save:&error])
            {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 */
                DLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }

    } else {

        // First save (child) context
        [context performBlock:^{

            NSError *error = nil;

            if ([context hasChanges] && ![context save:&error])
            {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 */
                DLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }];


        // Then save parent context
        [self.managedObjectContext performBlock:^{

            NSError *error = nil;

            if ([self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error]) {

                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 */
                DLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }];
    }
}
- (NSManagedObjectContext *)threadedManagedObjectContext {

    NSManagedObjectContext *threadedMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    threadedMoc.parentContext = self.managedObjectContext; //self.managedObjectContext is of type NSMainQueueConcurrencyType

    return threadedMoc;
}
这是保存的方法,
提醒
是一个
NSManagedObject
,当操作完成时,我调用一个完成块。但是,在完成块中,当获取一些NSManagedObject时,它们没有被更新(我猜是由于保存停止?)

threadedManagedObjectContext方法:

Thread 29, Queue : NSManagedObjectContext Queue
#0  0x9a5cf80e in semaphore_wait_trap ()
#1  0x02216f08 in _dispatch_thread_semaphore_wait ()
#2  0x02214b3a in _dispatch_barrier_sync_f_slow ()
#3  0x02214a5c in dispatch_barrier_sync_f ()
#4  0x01dfe03b in _perform ()
#5  0x01dfde9e in -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] ()
#6  0x01ddb33c in -[NSManagedObjectContext save:] ()
#7  0x00096213 in __45-[CoreDataHelper saveInManagedObjectContext:]_block_invoke_0 at /Users/peterwarbo/Documents/Projects/MessagePlanr/MessagePlanr/CoreDataHelper.m:307
#8  0x01e734b3 in developerSubmittedBlockToNSManagedObjectContextPerform_privateasync ()
- (void)saveInManagedObjectContext:(NSManagedObjectContext *)context {

    if (context == nil) {

        // Use default MOC
        context = self.managedObjectContext;

        NSError *error = nil;

        if (context != nil)
        {
            if ([context hasChanges] && ![context save:&error])
            {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 */
                DLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }

    } else {

        // First save (child) context
        [context performBlock:^{

            NSError *error = nil;

            if ([context hasChanges] && ![context save:&error])
            {
                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 */
                DLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }];


        // Then save parent context
        [self.managedObjectContext performBlock:^{

            NSError *error = nil;

            if ([self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error]) {

                /*
                 Replace this implementation with code to handle the error appropriately.

                 abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                 */
                DLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }];
    }
}
- (NSManagedObjectContext *)threadedManagedObjectContext {

    NSManagedObjectContext *threadedMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    threadedMoc.parentContext = self.managedObjectContext; //self.managedObjectContext is of type NSMainQueueConcurrencyType

    return threadedMoc;
}

出现此问题的原因是,我正在使用
performBlock:
异步保存,它会立即返回,因此当它被返回并且我的完成块被调用时,保存可能不会提交

因此,这个问题的答案是在
performBlockAndWait:


现在出现了另一个问题,使用
performBlock和wait:
是否有任何缺点?

出现这个问题是因为我正在使用
performBlock:
异步保存,它会立即返回,因此当它被返回并且我的完成块被调用时,保存可能不会被提交

因此,这个问题的答案是在
performBlockAndWait:


现在出现了另一个问题,使用
performBlock和wait:

在您的
saveInManagedObjectContext
方法中,尝试将父上下文保存在子上下文
performBlock
方法中,如果
statement@Yaman谢谢你的建议,但这不是问题所在。事实上,我是在对
performBlock*
API进行了一些调查之后发现这个问题的。很高兴它对您起到了作用。你能用你找到的解决方案更新你的帖子吗?它可以帮助其他有同样问题的人。@Yaman我回答了我自己的问题:)在
saveInManagedObjectContext
方法中,尝试将父上下文保存在子上下文
performBlock
方法和
if
statement@Yaman谢谢你的建议,但这不是问题所在。事实上,我是在对
performBlock*
API进行了一些调查之后发现这个问题的。很高兴它对您起到了作用。你能用你找到的解决方案更新你的帖子吗?它可以帮助其他有同样问题的人。@Yaman我回答了我自己的问题:)