CoreData在删除时崩溃等等

时间:2014-01-18 23:53:46

标签: ios iphone objective-c core-data

我对CoreData有一些非常神秘的行为。

我将添加Object。我保存这个对象。我获取新结果并重新加载集合视图(从中显示对象)。新对象出现了。 Hoorah!正如预期的那样。

我第二次执行此操作,但每次从现在开始(除非应用程序重新启动)从我的NSFetchedResultsController重新获取数据并重新加载集合视图时,新对象不会出现。< / p>

同样,如果我删除一个对象。第一次,A-OK!下次我这样做时,应用程序实际崩溃时出现以下错误:

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

一些代码的时间。我看不出任何问题,但现在是。我不会向你发送任何垃圾邮件,但如果有任何警报响起,我总是可以根据要求添加它。

从主视图控制器开始。这包含我的集合视图。就像一个注释,它有两个部分,每个部分从个人NSFetchedResultsController获取数据。我只是看到了这个具体的问题。相当标准的取得结果控制器。

- (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获取的。添加新对象时,用户位于模态(表单)视图控制器中。我创建了一个新对象,但是不要立即插入它,因为用户取消了:

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
            }];
        }
    }];

我使用委托将消息发送回主视图控制器,说明对象已保存。然后该方法获取新数据并重新加载集合视图以显示新对象:

-(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
                }
            }];

2 个答案:

答案 0 :(得分:3)

(来自我的上述评论:) 两个获取的结果控制器必须使用不同的 缓存(cacheName:参数)。我也(但我不是100%肯定) 没有部分,缓存不会带来任何好处,所以你也可以 试试cacheName:nil

答案 1 :(得分:0)

我相信你需要使用单独的ManagedObjectContexts来保存后台线程。

https://developer.apple.com/library/ios/documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html