ios-使用线程和核心数据时出现错误(objective-c) [英] ios - error when using threads and core data (objective-c)

查看:70
本文介绍了ios-使用线程和核心数据时出现错误(objective-c)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

制作一种删除核心数据,然后将其添加到后台的方法(以便核心数据可以更新)

Making a method that deletes core data and then adds it in the background (so core data can update)

(void) resetDatabase {
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        ConDAO *con = [[ConDAO alloc] init];
        DatabaseManager *manager = [DatabaseManager sharedManager];
        NSError * error;
        NSURL * storeURL = [[[manager managedObjectContext] persistentStoreCoordinator] URLForPersistentStore:[[[[manager managedObjectContext] persistentStoreCoordinator] persistentStores] lastObject]];
        [[manager managedObjectContext] reset];//to drop pending changes
        if ([[[manager managedObjectContext] persistentStoreCoordinator] removePersistentStore:[[[[manager managedObjectContext] persistentStoreCoordinator] persistentStores] lastObject] error:&error])
        {
            // remove the file containing the data
            [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
            //recreate the store like in the  appDelegate method
            [[[manager managedObjectContext] persistentStoreCoordinator] addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];//recreates the persistent store
        }
        [self populateDatabase:0 con:con];
        NSLog(@"*****************************");
        NSLog(@"updating");
        NSLog(@"*****************************");
        NSTimer *timer = [NSTimer timerWithTimeInterval:60.0
                                                 target:self
                                               selector:@selector(resetDatabase)
                                               userInfo:nil repeats:YES];
        [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    });
}

但是,在计时器运行并执行了几次函数后,我得到了错误

However, after the timer runs and the function is executed a few times I get the error

EXC_BAD_ACCESS(code = 1, address = 0x38)

采用以下方法:

- (void)newManagedCaf
{
    cafCards = [[NSManagedObject alloc] initWithEntity:cafDescription insertIntoManagedObjectContext:managedObjectContext];
}

发生错误的方法称为:

// First the student database is updated
- (void)populateDatabase:(int)tries con:(ConDAO *)con{
    DatabaseManager *manager = [DatabaseManager sharedManager];

    //Fetch greatest contact number in local database
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Caf_student_cards"];
    fetchRequest.fetchLimit = 1;
    fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"contact" ascending:NO]];
    NSError *error = nil;
    id cont = [[[manager managedObjectContext] executeFetchRequest:fetchRequest error:&error].firstObject valueForKey:@"contact"];
    int contact = 0;
    if (cont != nil){
        contact = [cont intValue];
    } //Pull students newer than the newest student in the local database
    //NSString *query = [NSString stringWithFormat:@"SELECT caf.user_id, caf.family_number, caf.card_number, caf.suspension_start_date, caf.suspension_end_date, caf.balance, util.room, caf.meal_plan_type, student.special_diet, student.specify_other, users.surname, users.type, users.name, users.contact from(SELECT * from caf_student_cards) AS caf LEFT JOIN (SELECT user_id, special_diet, specify_other FROM students) AS student ON caf.user_id = student.user_id LEFT JOIN (SELECT resource_id AS room, user_id FROM utilizations) AS util ON caf.user_id = util.user_id LEFT JOIN (SELECT surname, name, type, user_id, contact FROM system_users) AS users ON caf.user_id = users.user_id WHERE contact > %d", contact];

    NSString *query = @"GetCaf";
    [con executePreparedSQLAsync:query Parameter:@[[NSString stringWithFormat:@"%d",contact]] withCompletion:^(NSMutableArray *data, NSError *error){
        // Error encountered
        if(error != nil){
            NSLog(@"err: %@", error);
            // Retry up to twice to execute the query
            if(tries < 3){
                [self populateDatabase:(tries+1) con:con];
            }
            else{
                NSLog(@"%s %s %s","\n\n\n",[[error localizedDescription] UTF8String],"\n\n\n");
                dispatch_async(dispatch_get_main_queue(), ^{
                    // Show alert to tell user to reload this page
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"Error: %@", [error localizedDescription]] message:@"No connection, could not update local data." delegate:self cancelButtonTitle:@"Back" otherButtonTitles:@"Continue", nil];
                    [alert show];
                });
            }
        }
        else{
            // If successful, store the results in the local database
            for(NSMutableDictionary *result in data){
                [manager newManagedCaf];
                for (NSString *name in result){
                    if ([name isEqualToString:@"contact"]){
                    NSNumber *num = [NSNumber numberWithInteger:[[result valueForKey:name] integerValue]];
                        [[manager cafCards] setValue:num forKey:name];
                    }
                    else{
                        [[manager cafCards] setValue:[result valueForKey:name] forKey:name];
                    }
                }

                [[manager cafCards] setValue:[NSNumber numberWithBool:YES] forKey:@"synced"];

            }
            [[manager cafCards].managedObjectContext save:&error];
            if(error != nil){
                NSLog(@"Unable to save managed object context.");
                NSLog(@"%@, %@", error, error.localizedDescription);
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"Error: %@", [error localizedDescription]] message:@"Database not working, try again later or inform IT." delegate:self cancelButtonTitle:@"Back" otherButtonTitles:nil, nil];
                [alert show];
            }
            [self getImages:0 con:con withManager:manager];
       }
    }];
}

有时我还会在resetDatabase方法中收到以下错误:

Also sometimes I get the following error which occurs in resetDatabase method:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'nil is not a valid store.'


推荐答案

删除存储后,您似乎正在使用persistentStore的managedObjectContext。这是导致插入时崩溃的原因。

It looks like you are using the persistentStore's managedObjectContext after you have deleted the store. This is the cause of your crash on insert. the BAD_ACCESS is trying to insert to a nil store.

如果目标是9+,则可以使用 replacePersistentStoreAtUrl 替换数据存储。

If your target is 9+ you can use replacePersistentStoreAtUrl to replace the data store.

相关问题的链接此处

这篇关于ios-使用线程和核心数据时出现错误(objective-c)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆