我有两个实体,一个叫做 InProject
,它有几个属性和一个关系。关系是与另一个名为 Ins
的实体。
我正在编辑与 InProject
相关的 Ins
之一。我使用了 InProject
属性 ID
,然后返回一个 NSDictionary 值,该值具有多个键值,其中一个用于 Ins
数组。然后我找到我需要在 for 循环中编辑的 Ins 我编辑它们,但后来我变得不卡住,因为我不确定如何使用 *updated Ins
我需要弄清楚如何在覆盖我需要更新的 Ins
属性后保存 InProject
。
这是解决这个问题后我的代码的样子:
- (void)editSelectedins:(NSString *)projIDString UpdatedNSD:(NSMutableDictionary *)updatedNSD DPC:(int)dpc{
// get context
NSManagedObjectContext *context = [self managedObjectContext];
if (context == nil) {
NSLog(@"Nil");
}
else {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"InsProject" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error;
NSMutableArray *InsProjectDictionaryArray = [[NSMutableArray alloc] init];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (InsProject *insProj in fetchedObjects) {
NSMutableDictionary *tempInsProjectDictionaryArray = [[ NSMutableDictionary alloc] init];
[tempInsProjectDictionaryArray setObject:insProj.companyName forKey:@"CompanyName"];
[tempInsProjectDictionaryArray setObject:insProj.projNo forKey:@"ProjNo"];
[tempInsProjectDictionaryArray setObject:insProj.desc forKey:@"Desc"];
[tempInsProjectDictionaryArray setObject:insProj.guid forKey:@"GUID"];
[tempInsProjectDictionaryArray setObject:insProj.projID forKey:@"ProjID"];
[tempInsProjectDictionaryArray setObject:insProj.ins forKey:@"ins"];
[InsProjectDictionaryArray addObject:tempInsProjectDictionaryArray];
}
// now that you have the InsProjects, choose the one you are curently working on in insView using the projectID
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ProjID==%@",projIDString];
[fetchRequest setPredicate:predicate];
// new array with one value that was created using the NSPredicate ProjID
NSArray *tempInsProjectArray = [InsProjectDictionaryArray filteredArrayUsingPredicate:predicate];
// get ins array out of the NSDictionary to edit
NSSet *inssForInsProject = tempInsProjectArray[0][@"ins"];
NSMutableArray *tempAllinss = [[NSMutableArray alloc] init]; // this will contain everything, that means all repeated values are included
for (Items* currItem in [inssForInsProject allObjects]) {
NSArray *keys = [[[currItem entity] attributesByName] allKeys];
NSDictionary *dict = [currItem dictionaryWithValuesForKeys:keys];
[tempAllinss addObject:dict];
}
NSArray *myArray = [tempAllinss copy];
// get the correct items from myArray anything whos dpc matches the dpc parameter of this method
NSMutableArray *editedinsArray = [[NSMutableArray alloc] init];
for (int i = 0; i < [myArray count]; i++) {
NSMutableDictionary *tempinssDictionary = [myArray objectAtIndex:i];
// if you get a match put it into the new editedinsArray to be edited
if ([[tempinssDictionary objectForKey:@"dpc"] integerValue] == dpc) {
[editedinsArray addObject:tempinssDictionary];
}
}
// by now you should have three things
// 1, access to your ins coredata object //this s wrong I actually have access to insProject
// 2, the values you need to be edited saved into a NSArray (editedinsArray, which will be used to check against and keep old values correct)
// 3, UpdatedNSD which will be used to update any values that need to be updated.
// go through your values and update the ins object
int i = 0;
for (ins *temp in editedinsArray) {
NSDictionary *currentEditedins = [editedinsArray objectAtIndex:i];
i++;
// these values should stay the same so use currentEditedins which contains old vals
NSString *stringToNumberDpc = [currentEditedins valueForKey:@"dpc"];
int tempDpcNum = [stringToNumberDpc integerValue];
NSNumber *dpcNumber = [NSNumber numberWithInt:tempDpcNum];
temp.dpc = dpcNumber;
NSString *totDQtyString = [currentEditedins valueForKey:@"totDQty"];
if ((NSNull *)totDQtyString == [NSNull null]) {
temp.totDQty = @"";
} else {
temp.totDQty = totDQtyString;
}
NSString *totShipString = [currentEditedins valueForKey:@"totShip"];
if ((NSNull *)totShipString == [NSNull null]) {
temp.totShip = @"";
} else {
temp.totShip = totShipString;
}
// values to be updated so use updatedNSD wthich was passed in as method param with the new vals
temp.newInsComp = [updatedNSD valueForKey:@"newInsComp"];
temp.newDryComp = [updatedNSD valueForKey:@"newDryComp"];
temp.updatedRow = [updatedNSD valueForKey:@"updatedRow"];
}
#warning --- I have no idea what to do here... i.e. how do I update the tempInsProjectArray.ins values I have just updated in the above for loop then save context which I hope would update insProj and the ins entities involved.
//save
[context save:&error];
}
}
正如您在代码底部看到的那样,我用#warning 解释了我遇到问题的地方。如果我在 for 循环中记录 temp,我会完美地看到更新的值 我遇到的问题是如何更新我刚刚编辑的当前 tempInsProjectArray.ins 值?然后当然要保存它们。
最佳答案
您的代码非常需要简化。一些基本规则:
- 对变量使用带有 smallInitial 和 camelCase 的名称。所以不是
InsProjectDictionaryArray
而是insProjectDictionaryArray
。 - 这同样适用于指示托管对象的属性名称的字典键。所以
projNo
,而不是ProjNo
。 - 避免使用晦涩难懂的缩写。使用通俗易懂的英语,不是
projNo
,而是projectNumber
。什么是Ins
?什么是“dcp”? - 不要对实体名称使用复数形式。项目的合适名称是
Item
,而不是Items
- 当不可变版本可以使用时,不要使用可变版本的字典和数组。
- 避免复制数据,例如
[array copy]
。 - 当您有对象图时,请避免使用字典。对象图是核心数据创建的。它使带有值和键的字典变得不必要。
- 不要使用 ID。在大多数情况下,对象图也会呈现那些不必要的东西。如果您使用 ID,请勿使用字符串,而应使用数字,例如长整型或对象版本
NSNumber
。 - 从 Core Data 持久存储中获取数据时,不要获取所有数据并过滤结果。仅获取您需要的数据。
你想完成的事情肯定可以用几行代码来完成。我会尽量根据我的理解总结你想做的事情。
您的数据模型如下所示:
Project <----->> Item
其中项目处于称为 ins
的一对多关系中。我将重命名此 items
。我还假设您将您的 ID 重构为 NSNumber
类型。
myArray
之前的所有代码都可以替换为:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:"Project"];
request.predicate = [NSPredicate predicateWithFormat:@"projectID = %@", projectID];
request.fetchLimit = 1;
NSArray *fetchedObjects = [self.managedObjectContext
executeFetchRequest:request error:nil];
Project *project = fetchedObjects[0];
您现在只需使用 project.items
即可获得所有项目。我知道可能有多个项目具有 int
类型的神秘属性 dcp
(即托管对象的 NSNumber
),这等于传递给 dcp
参数。
NSSet *matchingItems = [project.items filteredSetUsingPredicate:
[NSPredicate predicateWithFormat:@"dcp = %@", @(dcp)]];
现在变得有点模糊了。如果 ins
实际上是 Item
类型,为什么在 for 循环中有 ins
类型?然后将它们转换成字典......这应该会产生编译器错误。或者您有另一个名为 ins
而不是 Ins
的类?
无论如何,如果您继续使用 Items,您只需使用您在字典中传递的内容来更新值:
for (Item *item in matchingItems) {
item.newInsComp = [updatedNSD valueForKey:@"newInsComp"];
item.newDryComp = [updatedNSD valueForKey:@"newDryComp"];
item.updatedRow = [updatedNSD valueForKey:@"updatedRow"];
}
[self.managedObjectContext save:nil];
完成!
顺便说一句,您可以通过将获取请求的实体名称设置为“Item”并设置以下谓词来使其更短:
[NSPredicate predicateWithFormat:@"project.projectID = %@ && dcp = %@",
projectID, @(dcp)];
关于ios - 编辑 CoreData 对象然后保存上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20011479/