挣扎于核心数据关系并删除对象

时间:2014-05-29 16:58:19

标签: xcode core-data entity-relationship cascade nsfetchrequest

我对Objective-C相对较新,并试图通过学习CoreData来努力,尽管有大量的Google搜索。我很好地掌握了mySQL和关系表,但我似乎无法理解如何让实体在CoreData中相互关联。

我喜欢在学习像CoreData这样的东西时为自己创建一些项目,所以我把它放在一起就是汽车服务跟踪器的简单概念(如换油,刹车等)。

我有2个代表车辆和油类变化的实体,如此......

enter image description here

enter image description here

......以及他们各自的关系。我不确定这是否需要一对一或一对多的关系,因为车辆会有很多换油,但也会有很多车......所以我猜这是我需要帮助理解的第一件事。

我正在使用SQLLite Manager来观察数据模型的变化。当我将Vehicle添加到我的Vehicle实体(基本上保存UITextFields)时,我可以看到对象在正确的实体中...

enter image description here

...当我将油更改添加到特定车辆时,我可以看到这些物体也被放入适当的实体......

enter image description here

..但是从下面可以看出,在尝试将特定换油与特定车辆相关联时似乎存在脱节......

enter image description here

现在,对于重要的问题......

1)。如何让个别换油仅与各自的车辆相关?现在无论选择哪种车辆,都会显示所有换油。我确信这与更新我提取的结果查询有关,但是从显示的表格中可以看出,我没有得到相应的换油次数。

2)。这可以通过理解问题1来解决......但如果我删除某个特定的车辆,那么我显然还需要删除与该车辆相关的任何换油。

我的保存方法如下。

- (IBAction)save:(id)sender {
Oil *oil = [NSEntityDescription insertNewObjectForEntityForName:@"Oil" inManagedObjectContext:self.managedObjectContext];
Vehicle *vehicle = [NSEntityDescription insertNewObjectForEntityForName:@"Vehicle" inManagedObjectContext:self.managedObjectContext];

// Which Vehicle
// newOil.vehicle = whichVehicle.text;
oil.vehicle = vehicle; // not working

// Format: Mileage
NSNumberFormatter *numberFormat = [[NSNumberFormatter alloc] init];
[numberFormat setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *myNumber = [numberFormat numberFromString:oilMileage.text];
oil.oilMileage = myNumber;

// Format: Date
NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
[dateFormat setDateFormat:@"MM-dd-yyyy"];
oil.oilDate = [dateFormat dateFromString:oilDate.text];

// Format: Notes
oil.oilNotes = oilNotes.text;

// save context
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate saveContext]; }

- >

- >

- >

- >

好的,我试图整合Dan Shelly建议的内容(这完全合情合理)但是我遇到了一些需要更多指导的障碍。

我的mainVC并没有使用tableView显示我的车辆(我将车辆总数限制为4,我用图标代表它们并将它们绑回CoreData中的vehicleID)。无论如何,因为它不是tableView我不能使用以下内容:

Vehicle *existingVehicle = (Vehicle *)[self.fetchedResultsController objectAtIndexPath:indexPath];

...因此,我在为获取的Vehicle对象创建实例时遇到问题,然后我可以将其传递给OilViewController。我有一个fetchRequest,它从CoreData返回正确的vehicleID,但我需要知道如何实际创建对象,以便我可以将它传递给OilViewController。我的fetchRequest看起来像这样......

- (void)fetchObjects {
NSLog(@"DVC-fetching Objects\n\n");

// Create Fetch Request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Vehicle" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];

// Set Search Criteria
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"vehicleID == %@", vehicleID];
[fetchRequest setPredicate:predicate];

NSError *error;
NSArray *array = [managedObjectContext executeFetchRequest:fetchRequest error:&error];

NSLog(@"Object ID: %@", [array valueForKey:@"objectID"]);
NSManagedObjectID *moID = [array valueForKey:@"objectID"];

if (array != nil) {
    NSUInteger count = [array count]; // May be 0 if the object has been deleted.
    Vehicle *existingVehicle = (Vehicle *)[self.managedObjectContext existingObjectWithID:moID error:&error];
    NSLog(@"Count: %lu", (unsigned long)count);
    NSLog(@"Fetched Vehicle ID: %@",predicate);
    NSLog(@"existingVehicle: %@", existingVehicle);

} else {
    // Deal with error.
}

}

但我收到以下错误:

由于未捕获的异常终止应用' NSInvalidArgumentException',原因:' - [__ NSArrayI isTemporaryID]:无法识别的选择器发送到实例0x11d5b660'

  • moID正确返回为" 0x8bb1980 x-coredata:// 6681B331-29F0-448B-82F1-4660E033A460 / Vehicle / p1"
  • 数组计数正在返回" 1" [正确]
  • 并且FetchVehicle ID正在返回" vehicleID == 1" [也正确]

如何为此返回的对象创建Vehicle实例,以便我可以将其传递给

1 个答案:

答案 0 :(得分:1)

1)如何让个别换油只涉及各自的车辆?

您已经...只有您当前正在将换油与空Vehicle物件相关联。这在车辆表中也可见(Z_PK = [3,4,5])。

当您需要添加新换油时,您可能已经可以访问此换油所需的相对Vehicle对象。
Vehicle对象可能是您在车辆视图控制器中选择的对象。

因此,每次创建换油时,不要插入Vehicle对象,只需将关系设置为现有车辆(您正在构建对象图,根据现有对象进行思考并将它们相互连接)。

2)删除

从图片中可以看出,您应该设置删除规则,以实现目标。当您删除Vehicle对象时,级联规则将删除相关的换油对象。当您删除换油对象时,相关的Vehicle油关系将无效。

总结一下:

获取现有的Vehicle对象:

//in your vehicle view controller :
Vehicle* existingVehicle = (Vehicle*)[self.fetchedResultsController objectAtIndexPath:indexPath];

将此对象传递给“换油视图控制器”。 添加新换油时,将车辆设置为现有对象:

Oil *oil = [NSEntityDescription insertNewObjectForEntityForName:@"Oil" inManagedObjectContext:self.managedObjectContext];
oil.vehicle = existingVehicle; // the one you passed along to this scope
//The rest of the oil content setting
//DON'T FORGET TO SAVE!

您可能希望将关系类型更改为多种类型的关系(Vehicle可能有多次换油)。
这不会改变您的换油创建代码。

要查看特定Vehicle对象的机油更改,您必须使用传递给机油更换视图控制器的现有车辆对象,并在FRC提取请求的谓词中使用它:

NSPredicate* p = [NSPredicate predicateWithFormat:@"vehicle = %@",existingVehicle];
fetchRequest.predicate = p;