【发布时间】:2021-06-26 20:00:23
【问题描述】:
这个问题在 Stack Overflow 上似乎已经回答了很多次 - 但它仍然不适用于我的用例。核心数据大部分工作正常。关闭文档时出现问题 - 那时我需要重置核心数据,准备好加载下一个文档。实际发生的情况是,下一个要加载的 Document 会加载其所有数据以及所有以前的 Documents 数据 - 并且在应用程序退出并再次重新打开之前它不会重置。
我有一个基于 NSDocument 的应用程序,它可以加载许多不同的文档类型。每种文档类型都在其自己的类中进行描述。例如,Foo 可能是一个非常简单的文档类型,很小,基于文本,处理起来没有问题,因此不需要复杂的类来加载它。另一方面,Bar 是一个巨大的复杂数据库,大小为 GB - 将其全部加载到内存中是没有意义的。
我的 Bar 类使用 Core Data - 它是唯一需要的,因此也是唯一包含此逻辑的。我提到这一点是因为几乎所有关于如何使用 Core Data 的描述都将 Core Data 代码放在 App Delegate 中——这可能是有充分理由的!
在我的栏标题中,我的核心数据设置如下:
@property (nonatomic, strong, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (nonatomic, strong, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong, readonly) NSDate *readStart;
在我的 Bar .m 中,我有以下内容:
- (NSURL *)dataStoreURL {
NSString *docDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
//NSString* filename = [NSString stringWithFormat:@"%@.sql",[StringWangers generateUUIDString]];
NSString* filename = @"datastore.sql";
return [NSURL fileURLWithPath:[docDir stringByAppendingPathComponent:filename]];
}
- (NSManagedObjectModel *)managedObjectModel {
if (_managedObjectModel) {
return _managedObjectModel;
}
_managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator) {
return _persistentStoreCoordinator;
}
[NSFileManager.defaultManager removeItemAtURL:self.dataStoreURL error:nil]; // this isn't supposed to be persistent - clear out old crap
NSError *error = nil;
NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption: @(YES), NSInferMappingModelAutomaticallyOption: @(YES)};
_persistentStoreCoordinator = [NSPersistentStoreCoordinator.alloc initWithManagedObjectModel:self.managedObjectModel];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:self.dataStoreURL
options:options
error:&error]) {
NSLog(@"Unresolved Core Data error with persistentStoreCoordinator: %@, %@", error, [error userInfo]);
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext) {
return _managedObjectContext;
}
if ([self persistentStoreCoordinator]) {
_managedObjectContext = [NSManagedObjectContext.alloc initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
}
return _managedObjectContext;
}
我已经尝试了很多方法来删除这些讨厌的数据 - 包括腰带和牙套,所有东西(我真的不喜欢这样做,因为我想了解发生了什么 - 但我很绝望!) - 这个是“一切”状态……
-(void)deinitialise {
@try {
NSLog(@"Deleting old core storage");
NSArray *allEntities = self.managedObjectModel.entities;
for (NSEntityDescription *entityDescription in allEntities) {
NSFetchRequest *fetchRequest = NSFetchRequest.new;
[fetchRequest setEntity:entityDescription];
fetchRequest.includesPropertyValues = NO;
fetchRequest.includesSubentities = NO;
NSLog(@"%@",fetchRequest);
NSError *error = nil;
NSArray *items;
if (self.managedObjectContext &&
fetchRequest &&
([fetchRequest.sortDescriptors isKindOfClass:NSArray.class] && fetchRequest.sortDescriptors.count > 0) &&
fetchRequest.predicate) {
items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
}
if (error) {
NSLog(@"Error requesting items from Core Data: %@", error.localizedDescription);
}
for (NSManagedObject *managedObject in items) {
[self.managedObjectContext deleteObject:managedObject];
[self.managedObjectContext save:&error];
if (error) {
NSLog(@"Error deleting items from Core Data: %@", error.localizedDescription);
}
}
}
}
@catch (NSException *exception) {
NSLog(@"Error deleting persistent storage - Exception: %@", exception);
}
NSError *error = nil;
NSArray* persistentStoreArray = self.persistentStoreCoordinator.persistentStores;
for (id store in persistentStoreArray) {
[self.persistentStoreCoordinator removePersistentStore:store error:&error];
if (error) {
NSLog(@"Error Removing Persistent Store: %@", error.localizedDescription);
}
NSString* storePath = [store URL].path;
NSLog(@"%@",storePath);
[NSFileManager.defaultManager removeItemAtPath:storePath error:&error];
if (error) {
NSLog(@"Error Deleting Persistent Store: %@", error.localizedDescription);
}
}
self.persistentStoreCoordinator = nil;
}
有趣的是,- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 仅在我的 Bar 类在文档加载时第一次被调用时被调用,但每次我调用我的 reinitialise 类时。
希望这对某人有意义 - '因为我没有想法。
【问题讨论】:
-
几乎所有关于如何使用 Core Data 的描述都适用于 iOS,而
NSPersistentDocument在 iOS 上不可用。NSPersistentDocument没有将 Core Data 代码放在 App Delegate 中。创建一个 Xcode 项目,macOS Cocoa 应用,基于文档,Uses Core Data 看看。 -
您能否澄清一下,当您关闭文档时,您想删除用户 Mac 中的所有数据,而不仅仅是将其从内存中取出?这样就不可能再次加载该数据?我不认为那是你想要的,但既然你像这样使用
deleteObject,似乎它可能就是这样。 -
我现在会满足于将其从内存中删除 - 但你说得对,我真正想要的是完全删除它(这就是我也尝试 removeItemAtPath 的原因)
-
…另外,这是在 Mac 上,而不是在 iOS 上。
-
在反初始化代码中,您的 if 条件包含 fetchRequest.predicate,但您从未设置谓词:因此 fetchRequest 永远不会执行。关于FileManager的操作,你检查过错误吗?更广泛地说,您可能还需要删除 .sqlite-wal 和 -shm 文件(或使用destroyPersistentStore)。
标签: objective-c cocoa core-data