我将创建三个实体,Supermarket、Product 和 SupermaketProductDetails,其属性和关系如下:
Supermarket:
Attributes: name, location, phone number
Relationship (to many): productDetails
Product:
Attributes: name, price, company
Relationship (to many): supermarketDetails
SupermarketProductDetails:
Attributes: priceofProductforGivenMarket, primaryProductforGivenMarket
Relationships: (to one) supermarket, (to one) product
在Xcode中,指明Supermarket实体中productDetails关系的“目的地”是SupermarketProductDetails实体,逆超市,同样将SupermarketProductDetails实体设置为Product实体中supermarketDetails的目的地,逆产品。
然后,我将首先解析超市的 JSON 数据,创建 Supermarket 对象并设置名称、位置和电话号码,但不为产品关系输入任何内容。同样,解析产品 JSON 并创建所有 Products 对象。然后我会解析连接表,并创建 SupermarketProductDetails 对象。根据你的 JSON 数据设置属性,并执行一次 fetch 以获取具有正确名称的 Supermarket 实体,同样获取具有正确名称的 Product 实体,然后直接设置这些关系。
编辑:
假设您将连接表中的每一行解析为四个 NSString:nameofsupermarket、nameofproduct、priceofProductforGivenMarket 和 primaryProductforGivenMarket。然后对于每一行...
// First fetch the correct Supermarket...
NSFetchRequest *supermarketFetch = [NSFetchRequest fetchRequestWithEntityName:@"Supermarket"]
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like %@",nameofsupermarket];
supermarketFetch.predicate = predicate;
NSError *error;
NSArray *results = [context executeFetchRequest:supermarketFetch error:&error];
// should really check for errors, and that we get one and only one supermarket
NSLog(@"Supermarket fetch returned %i results",[results count]); // should be only 1!
mySupermarket = (NSManagedObject *)[results firstObject];
if (![[mySupermarket valueForKey:@"name"] isEqualToString:nameofsupermarket]) {
NSLog(@"Wrong supermarket fetched");
}
// Now fetch the product...
NSFetchRequest *productFetch = [NSFetchRequest fetchRequestWithEntityName:@"Product"]
predicate = [NSPredicate predicateWithFormat:@"name like %@",nameofproduct];
productFetch.predicate = predicate;
results = [context executeFetchRequest:productFetch error:&error];
// should really check for errors, and that we get one and only one product
NSLog(@"Product fetch returned %i results",[results count]); // should be only 1!
myProduct = (NSManagedObject *)[results firstObject];
if (![[myProduct valueForKey:@"name"] isEqualToString:nameofproduct]) {
NSLog(@"Wrong product fetched");
}
// Now create the SupermarketProductDetails entity:
NSManagedObject *mySupermarketProductDetails = [NSEntityDescription insertNewObjectForEntityForName:@"SupermarketProductDetails" inManagedObjectContext:context];
// set attributes...
[mySupermarketProductDetails setValue:primaryProductForGivenMarket forKey:@"primaryProductForGivenMarket"];
[mySupermarketProductDetails setValue:priceOfProductForGivenMarket forKey:@"priceOfProductForGivenMarket"];
// set relationships...
[mySupermarketProductDetails setValue:mySupermarket forKey:@"supermarket"];
[mySupermarketProductDetails setValue:myProduct forKey:@"product"];
[context save:&error];
// should check for errors...
请注意,您只需要设置这些关系的一侧 - CoreData 会为您更新另一侧(即,它将 mySupermarketDetails 添加到 myProduct 的 supermarketDetails 集合中,等等)。另请注意,(一对一)关系(例如超市)的“价值”是目标对象本身(例如 mySupermarket);您不使用名称或任何其他键。 Coredata(隐藏在底层 sql 表中)使用唯一的 objectID 进行链接。
(可能有更有效的方法来执行此操作,而不是为每个 SupermarketProductDetails 条目进行两次提取,但这会起作用。)
EDIT2:请注意,以上假设您的实体都实现为 NSManagedObjects。如果您为每个实体创建了单独的子类,那么您可以简化上面的一些代码。例如,valueForKey: 和 setValue:forKey: 可以使用点表示法替换为等效的属性访问器方法,例如:
[mySupermarketProductDetails setValue:primaryProductForGivenMarket forKey:@"primaryProductForGivenMarket"];
会变成:
mySupermarketProductDetails.primaryProductForGivenMarket = primaryProductForGivenMarket;
和
[mySupermarket valueForKey:@"name"]
可以替换为:
mySupermarket.name
同样,应该使用适当的子类而不是 NSManagedObject 创建对象。例如。
NSManagedObject *mySupermarketProductDetails = [NSEntityDescription insertNewObjectForEntityForName:@"SupermarketProductDetails" inManagedObjectContext:context];
会变成
SupermarketProductDetails *mySupermarketProductDetails = [NSEntityDescription insertNewObjectForEntityForName:@"SupermarketProductDetails" inManagedObjectContext:context];