问题描述
制作一种删除核心数据,然后将其添加到后台的方法(以便核心数据可以更新)
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)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!