该应用程序被CoreData崩溃

时间:2013-12-29 14:30:34

标签: ios objective-c xcode core-data

我正在开发应用程序,它使用CoreData。

但是当我按下AddNewObject的完成按钮时,它会崩溃应用程序。

iPhone screens

MasterViewController.m

...

- (void)addNewCountdown:(NSString*)title date:(NSDate*)date main:(BOOL)main notification:(BOOL)notification notificationDate:(NSInteger)notificationDate
{
    [self managedObjectContext];

    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
    NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

    // If appropriate, configure the new managed object.
    // Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template.
    [newManagedObject setValue:title forKey:@"title"];

    [newManagedObject setValue:date forKey:@"date"];

    [newManagedObject setValue:[NSNumber numberWithBool:notification] forKey:@"notification"];

    // Save the context.
    NSError *error = nil;
    if (![context save:&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();
    }
}

...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
        [[segue destinationViewController] setDetailItem:object];
    }
}

#pragma mark - Fetched results controller

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO];
    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.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController 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 _fetchedResultsController;
}

...

NewObjectViewController.m

- (IBAction)Done:(id)sender
{
    ...
    else{
        NSIndexPath *indexPath_two = [NSIndexPath indexPathForRow:0 inSection:1];
        DatePickerCell *cell_two = (DatePickerCell*)[self.tableView cellForRowAtIndexPath:indexPath_two];

        [cell_two.timer invalidate];

        NSLog(@"Text:%@",text);

        if ([cell_two.timer isValid] == YES) {
            NSLog(@"timer yes");
        }

        MasterViewController *master =  [[MasterViewController alloc] initWithNibName:nil bundle:[NSBundle mainBundle]];

        [master addNewCountdown:text
                           date:cell_2.DatePicker.date main:cell_3.mainSwitch.on
                   notification:cell_4.mainSwitch.on notificationDate:_beforeMinute];

        [self dismissViewControllerAnimated:YES completion:nil];
    }

以及此处的日志。

it happens when I push done button.

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Event''

为什么会这样?

我该怎么办?

请告诉我一个答案。

如果您想了解其他内容,请添加评论。

1 个答案:

答案 0 :(得分:0)

添加一些断点以逐步执行并检查变量值。我将从fetchedResultsManager访问器开始,特别是行:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];

检查您的managedObjectContext属性是否为nil。还要检查您的托管对象模型是否有一个名为Event的实体(注意拼写和大小写)。这些是您的错误消息所指示的内容。

知道发生异常的行是有帮助的。转到左侧的断点导航器窗格,然后按下底部的“+”按钮。选择添加例外中断。这将在异常发生时停止调试器,您可以检查相关变量值以获取线索。

我想到的另一件事是你需要缓存fetchedResults。我之前看到的问题是缓存过时和奇怪的崩溃开始了。它是否有机会第一次成功并在此后崩溃?我通常在创建新实例之前刷新缓存:

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    // flush cache before creating new frc
    [NSFetchedResultsController deleteCacheWithName:@"Master"];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    ...

我可能错了,但我不相信你从缓存结果中得到任何有益的好处,除非你真的在处理庞大的数据集和处理。我通常会将缓存保留为nil,并且看不到滚动问题。