核心数据:插入在全局队列中崩溃的对象[ARC - iPhone模拟器6.1]

时间:2013-06-06 09:37:21

标签: iphone ios objective-c core-data automatic-ref-counting

我有一个非常简单的Core Data演示,其中只有一个按钮。

当我点击“运行”按钮时,应用程序在for循环中创建10,000个对象,在全局队列中运行

更新以获取更多详细信息:如果我将for-loop放在主线程中,它运行良好。

我的意图更新:我知道MOC不是线程安全的,但根据the Apple doc,我们也可以使用串行队列来访问MOC,而串行队列使用更多比一个线程。

在这里,我创建了核心数据堆栈:

#pragma mark - Core Data Stack

- (NSManagedObjectContext *)managedObjectContext
{
    if (nil != _managedObjectContext) {
        return _managedObjectContext;
    }

    _managedObjectContext = [[NSManagedObjectContext alloc] init];

    if (self.persistentStoreCoordinator) {
        [_managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
    }

    return _managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel
{
    if (nil != _managedObjectModel) {
        return _managedObjectModel;
    }

    _managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
    return _managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (nil != _persistentStoreCoordinator) {
        return _persistentStoreCoordinator;
    }

    NSString *storeType = NSSQLiteStoreType;
    NSString *storeName = @"model.sqlite";
    NSURL *storeURL = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:storeName]];

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];

    NSError *error = nil;
    if (![_persistentStoreCoordinator addPersistentStoreWithType:storeType
                                                   configuration:nil
                                                             URL:storeURL
                                                         options:nil
                                                           error:&error])
    {
        NSLog(@"Error : %@\n", [error localizedDescription]);
        NSAssert1(YES, @"Failed to create store %@ with NSSQLiteStoreType", [storeURL path]);
    }

    return _persistentStoreCoordinator;
}

#pragma mark -
#pragma mark Application's Documents Directory

- (NSString *)applicationDocumentsDirectory
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
    return basePath;
}
应用推出后

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.

    if (self.managedObjectContext) {
        ;
    }

    return YES;
}

当我点击按钮时:

- (IBAction)runButtonDidClick:(id)sender
{
    /**
     * Access the moc using different threads to make deadlock.
     */

    [self runSave];
}

- (void)runSave
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
        NSManagedObjectContext *moc = appDelegate.managedObjectContext;

        if (moc) {
            for (int j = 0; j < 10000; ++j) {
                People *people = [NSEntityDescription insertNewObjectForEntityForName:@"People" inManagedObjectContext:moc];
                people.name = @"noname";
            }

            NSLog(@"**********IN SAVE %@", [NSThread currentThread]);
            NSError *error = nil;
            if ([moc save:&error]) {
                ;
            }

            NSLog(@"**********OUT SAVE %@", [NSThread currentThread]);
        }
    });
}

有时单击运行按钮,可能是2或3或4 ......它崩溃

我无法弄清楚为什么...... 谢谢你的帮助。

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:3)

核心数据应该始终在具有moc的线程上工作。 performBlockperformBlockAndWait的唯一工作是处理线程安全问题。随着它插入到Core Data将始终在正确的线程中运行。你可以在你想要的任何线程上定义moc - performBlock总是选择正确的线程。

所以:

[self.managedObjectContext performBlock:^{
            for(NSDictionary *dic in arr) {
                //inserting here!
            }
}];

在你的情况下:

- (void)runSave
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
        NSManagedObjectContext *moc = appDelegate.managedObjectContext;

        if (moc) {

          [moc performBlock:^{
            for (int j = 0; j < 10000; ++j) {
                People *people = [NSEntityDescription insertNewObjectForEntityForName:@"People" inManagedObjectContext:moc];
                people.name = @"noname";
            }
            NSError *error = nil;
            if ([moc save:&error]) {
                ;
            }
         }];
        }
    });
}