I have two entities, one called InProject
that has several attributes and one relationship. the relationship is with another entity called Ins
.
I am editing one of the Ins
that is related to InProject
. I used InProject
attribute ID
which then returns a NSDictionary value that has several key-values one of which is for an array of Ins
. I then find the Ins I need to edit in a for loop I edit them, but then I become unstuck because I am not sure how to save the contect of InProject with the *updated Ins
I need to figure out how to save InProject
after I have overwritten the Ins
attributes I need to update.
This is what my code looks like after battling this problem:
- (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];
}
}
As you can see at the bottom of the code with #warning I explain where I am having the issue. if I log temp inside the for loop I see the updated values perfectly the issue I am having is how do I then update the current tempInsProjectArray.ins values that I have just edited? then save them of course.
Your code is in great need of simplification. Some ground rules:
InsProjectDictionaryArray
but insProjectDictionaryArray
. projNo
, not ProjNo
. projNo
but projectNumber
. What is an Ins
? What is "dcp"?Item
, not Items
[array copy]
.NSNumber
.What you want to accomplish can surely be done in a few lines of code. I will try to summarize what you want to do as far as I understand it.
Your data model looks something like this:
Project <----->> Item
Where the items are in a to-many relationship called ins
. I will rename this items
. I will also assume that you will refactor your IDs to be of type NSNumber
.
All the code up to myArray
could be substituted with this:
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];
You now have all items available simply with project.items
. I understand that there could be more than one item with a mysterious attribute dcp
of type int
(i.e. NSNumber
for managed objects), that is equal to the dcp
parameter passed.
NSSet *matchingItems = [project.items filteredSetUsingPredicate:
[NSPredicate predicateWithFormat:@"dcp = %@", @(dcp)]];
Now it becomes a bit murky. Why do you have type ins
in your for loop if the ins
are actually of type Item
? You then cast them into a dictionary... This should generate a compiler error. Or you have another class called ins
instead of Ins
??
Anyway, if you stay with the Items you can just update the values with what you pass in your dictionary:
for (Item *item in matchingItems) {
item.newInsComp = [updatedNSD valueForKey:@"newInsComp"];
item.newDryComp = [updatedNSD valueForKey:@"newDryComp"];
item.updatedRow = [updatedNSD valueForKey:@"updatedRow"];
}
[self.managedObjectContext save:nil];
Done!
BTW you could make it even shorter by setting the entity name of the fetch request to "Item" and setting the following predicate:
[NSPredicate predicateWithFormat:@"project.projectID = %@ && dcp = %@",
projectID, @(dcp)];