我对 CoreData 有一些非常神秘的行为。
我将添加一个对象
。我保存这个对象。我获取新结果并重新加载 Collection View (从中显示对象)。新对象出现了。欢呼!正如预期的那样。
我第二次这样做了,但是从现在开始(除非重新启动应用程序)每次从我的 NSFetchedResultsController
重新获取数据并重新加载 Collection View 时,新对象都不会出现。
同样,如果我删除一个对象。第一次,好的!下次我这样做时,应用程序实际上崩溃并出现以下错误:
(Aircraft
是我的 NSManagedObject
)
Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xd0000000000c0000 <x-coredata://C418948D-90CD-40E9-A502-C4CAB0134419/Aircraft/p3>''
*** First throw call stack:
(0x18b79f09c 0x197ad5d78 0x18b4a77ac 0x18b4a6cac 0x18b4a6b00 0x100034438 0x18e6d8a44 0x18e6d6dc0 0x18e6d2e44 0x18e66ed78 0x18e26b0cc 0x18e265c94 0x18e265b4c 0x18e2653d4 0x18e265178 0x18e25ea30 0x18b75f7e0 0x18b75ca68 0x18b75cdf4 0x18b69db38 0x19106f830 0x18e6dc0e8 0x1000217dc 0x1980bfaa0)
libc++abi.dylib: terminating with uncaught exception of type _NSCoreDataException
是时候编写一些代码了。我看不出有任何问题,但它就在这里。我不会向您发送垃圾邮件,但如果有什么东西响起任何警报,我可以随时根据要求添加它。
从主视图 Controller 开始。这包含我的收藏 View 。请注意,它有两个部分,每个部分从一个单独的 NSFetchedResultsController
中获取数据。不过,我只看到了这个特定问题。相当标准的获取结果 Controller 。
- (NSFetchedResultsController *)aircraftFetchedResultsController
{
if (_aircraftFetchedResultsController != nil) {
return _aircraftFetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Aircraft" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:50];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.aircraftFetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.aircraftFetchedResultsController performFetch:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _aircraftFetchedResultsController;
}
我在任何使用 NSManagedObjectContext
的地方都从我的 AppDelegate
获取它。添加新对象时,用户处于模态(表单) View Controller 中。我创建了一个新对象,但不立即插入它,以防用户取消:
SLAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Aircraft" inManagedObjectContext:managedObjectContext];
self.aircraft = [[Aircraft alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
然后,完成后,保存对象:
SLAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
//Only need to insert the new object if its 'NEW' else just save the existing one we are editing
if (!isEditing)
{
//Create new aircraft
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
//We are definetly saving the object, so now we insert it
[managedObjectContext insertObject:self.aircraft];
}
//Save
[appDelegate saveContextWithCompletionBlock:^(BOOL didSaveSuccessfully) {
if (didSaveSuccessfully)
{
[self dismissViewControllerAnimated:YES completion:^{
[delegate addAircraftDidSave:YES];
}];
}
else
{
[self dismissViewControllerAnimated:YES completion:^{
//ALERT with error
}];
}
}];
我使用委托(delegate)向主视图 Controller 发送一条消息,说明对象已保存。然后该方法获取新数据并重新加载 Collection View 以显示新对象:
-(void)fetchAircraft
{
NSError *error;
if (![[self aircraftFetchedResultsController] performFetch:&error])
{
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
[UIAlertView showGenericErrorAlert];
}
//Success, we have results
else
{
[self.collectionView reloadData];
}
}
完成。正如我所说,这第一次起作用,然后开始行动。同样,你可以用保存代码代替我的删除代码,非常相似,删除并保存更改:
SLAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = appDelegate.managedObjectContext;
[managedObjectContext deleteObject:self.aircraft];
[appDelegate saveContextWithCompletionBlock:^(BOOL didSaveSuccessfully) {
if (didSaveSuccessfully)
{
[self dismissViewControllerAnimated:YES completion:^{
[delegate addAircraftDidSave:YES];
}];
}
else
{
//ALERT with error
}
}];
最佳答案
(来 self 上面的评论:) 两个获取的结果 Controller 必须使用不同的
缓存(缓存名称:
参数)。我也认为(但我不是 100% 确定)
没有部分,缓存没有任何优势,所以你也可以
试试 cacheName:nil
。
关于ios - 删除时 CoreData 崩溃等等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21211426/