ios - 编辑 CoreData 对象然后保存上下文

标签 ios core-data nsdictionary nsmutabledictionary nsset

我有两个实体,一个叫做 InProject,它有几个属性和一个关系。关系是与另一个名为 Ins 的实体。

我正在编辑与 InProject 相关的 Ins 之一。我使用了 InProject 属性 ID,然后返回一个 NSDictionary 值,该值具有多个键值,其中一个用于 Ins 数组。然后我找到我需要在 for 循环中编辑的 Ins 我编辑它们,但后来我变得不卡住,因为我不确定如何使用 *updated Ins

保存 InProject 的内容

我需要弄清楚如何在覆盖我需要更新的 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 值?然后当然要保存它们。

最佳答案

您的代码非常需要简化。一些基本规则:

  1. 对变量使用带有 smallInitial 和 camelCase 的名称。所以不是 InsProjectDictionaryArray 而是 insProjectDictionaryArray
  2. 这同样适用于指示托管对象的属性名称的字典键。所以 projNo,而不是 ProjNo
  3. 避免使用晦涩难懂的缩写。使用通俗易懂的英语,不是 projNo,而是 projectNumber。什么是 Ins?什么是“dcp”?
  4. 不要对实体名称使用复数形式。项目的合适名称是 Item,而不是 Items
  5. 当不可变版本可以使用时,不要使用可变版本的字典和数组。
  6. 避免复制数据,例如 [array copy]
  7. 当您有对象图时,请避免使用字典。对象图是核心数据创建的。它使带有值和键的字典变得不必要。
  8. 不要使用 ID。在大多数情况下,对象图也会呈现那些不必要的东西。如果您使用 ID,请勿使用字符串,而应使用数字,例如长整型或对象版本 NSNumber
  9. 从 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/

相关文章:

ios - 向 UITextField、UILabel、UIView 自定义类添加自定义功能

swift - 这是 WWDC 2014 示例代码的错误吗?

objective-c - 当我创建一个整数作为对象的 NSDictionary 时应用程序崩溃

java - 将 HTTP 响应(Java "Properties"流格式)转换为 NSDictionary

iOS:plist继承

ios - 如何将图像从 tableView 传输到另一个 imageViewController?

ios - 自定义UIButton时不同状态的IBInpectable属性

ios - 核心数据迁移问题: storePath cannot be initiated

iphone - Core Data 对多关系获取数据

ios - 从 NSDictionary 获取值(value)不起作用