Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/110.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
核心数据:在全局队列中插入崩溃的对象[ARC-iPhone simulator 6.1]_Iphone_Ios_Objective C_Core Data_Automatic Ref Counting - Fatal编程技术网

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

核心数据:在全局队列中插入崩溃的对象[ARC-iPhone simulator 6.1],iphone,ios,objective-c,core-data,automatic-ref-counting,Iphone,Ios,Objective C,Core Data,Automatic Ref Counting,我有一个非常简单的核心数据演示,其中只有一个按钮 当我单击“运行”按钮时,应用程序在for循环中创建10000个对象,该循环在全局队列中运行 更新以了解更多细节:如果我将for循环放在主线程中,它运行良好。 出于我的目的更新:我知道MOC不是线程安全的,但根据,我们也可以使用串行队列访问MOC,并且串行队列使用多个线程。 在这里,我创建了核心数据堆栈: #pragma mark - Core Data Stack - (NSManagedObjectContext *)managedObjec

我有一个非常简单的核心数据演示,其中只有一个按钮

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

更新以了解更多细节:如果我将for循环放在主线程中,它运行良好。

出于我的目的更新:我知道MOC不是线程安全的,但根据,我们也可以使用串行队列访问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]);
        }
    });
}
-(iAction)运行按钮单击:(id)发送方
{
/**
*使用不同的线程访问moc以产生死锁。
*/
[自动运行保存];
}
-(void)运行保存
{
调度异步(调度获取全局队列(调度队列优先级默认为0)^{
AppDelegate*AppDelegate=[[UIApplication sharedApplication]委托];
NSManagedObjectContext*moc=appDelegate.managedObjectContext;
如果(主运行中心){
对于(int j=0;j<10000;++j){
People*People=[NSEntityDescription insertNewObjectForEntityForName:@“People”位于托管对象上下文:moc];
people.name=@“noname”;
}
NSLog(@“******在SAVE%@”中,[NSThread currentThread]);
n错误*错误=nil;
如果([moc保存:&错误]){
;
}
NSLog(@“*********输出保存%@”,[NSThread currentThread]);
}
});
}
如果要多次单击“运行”按钮,可能需要2次、3次或4次。。。它崩溃了

我不明白为什么。。。 谢谢你的帮助


核心数据应始终在具有moc的线程上工作。
performBlock
performBlock和wait
的唯一任务是确保线程安全。通过它,插入核心数据将始终在正确的线程中运行。您可以在任何线程上定义moc-
performBlock
始终选择正确的线程

因此:

就你而言:

- (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]) {
                ;
            }
         }];
        }
    });
}
-(void)运行保存
{
调度异步(调度获取全局队列(调度队列优先级默认为0)^{
AppDelegate*AppDelegate=[[UIApplication sharedApplication]委托];
NSManagedObjectContext*moc=appDelegate.managedObjectContext;
如果(主运行中心){
[主运行中心性能块:^{
对于(int j=0;j<10000;++j){
People*People=[NSEntityDescription insertNewObjectForEntityForName:@“People”位于托管对象上下文:moc];
people.name=@“noname”;
}
n错误*错误=nil;
如果([moc保存:&错误]){
;
}
}];
}
});
}

NSManagedObjectContext不是线程安全的。为什么您有意在并发队列上使用它,以便在不同的线程上使用相同的MOC我们如何理解“使用不同线程访问moc以产生死锁”的注释顺便说一句,我看不出你实际上在哪里创建了一个持久性存储。@MartinR谢谢。实际上,我有意在不同的线程中使用MOC&已经创建了sqlite文件。我知道MOC不是线程安全的,但在这里,我只是在点击按钮时访问MOC。一次访问,一个线程,类似于串行队列?@JasonLee right-线程对MOC来说并不重要,但它应该始终是同一个线程
调度\u获取\u全局\u队列(调度\u队列\u优先级\u默认值,0)
返回一个并发队列,而不是串行队列。并发队列使用多个线程并发执行任务。@SimpleMan是的,但是线程可以逐个访问MOC,对吗?谢谢,但是串行队列呢?串行队列正在使用多个线程。我将此添加到我的答案中:
performBlock
performBlockAndWait
的唯一任务是确保线程安全。通过它,插入核心数据将始终在正确的线程中运行。您可以在任何线程上定义moc-
performBlock
始终选择正确的线程。
- (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]) {
                ;
            }
         }];
        }
    });
}