Reputation: 4797
I have gone over this over and over, and cannot for the life of me figure out why assigning a relationship through setValue:forKey: is not working. My method is below.
-(void)saveNewCartItemName:(NSString *)name Price:(float)price Qty:(int)qty Tax:(int)tax inCart:(NSDate *)cartDate{
NSManagedObject *newItem = [NSEntityDescription insertNewObjectForEntityForName:@"Item"
inManagedObjectContext:self.appDelegate.managedObjectContext];
NSFetchRequest *query = [[NSFetchRequest alloc] initWithEntityName:@"Cart"];
NSLog(@"cartDate = %@", cartDate);
[query setPredicate:[NSPredicate predicateWithFormat:@"cartDate = %@", cartDate]];
NSError *error;
NSMutableArray *queryResults = [[self.appDelegate.managedObjectContext executeFetchRequest:query error:&error] mutableCopy];
NSLog(@"queryResults count = %d", [queryResults count]);
if ([queryResults count] == 1) [newItem setValue:[queryResults objectAtIndex:0] forKey:@"cartThatHasItem"];
[newItem setValue:name forKey:@"itemName"];
[newItem setValue:[NSNumber numberWithFloat:price] forKey:@"itemPrice"];
[newItem setValue:[NSNumber numberWithInt:qty] forKey:@"itemQty"];
[newItem setValue:[NSNumber numberWithInt:tax] forKey:@"itemTax"];
[self.appDelegate.managedObjectContext save:&error];
}
The line that it crashes on every time is:
if ([queryResults count] == 1) [newItem setValue:[queryResults objectAtIndex:0] forKey:@"cartThatHasItem"];
My NSLog shows that there is a NSManagedObject to assign the relationship to, and I have double checked the name in the forKey: that there are no typos. All that Xcode tells me is that it prints out '(null)' on my console and then tells me 'libc++abi.dylib: terminate called throwing an exception' on the next line.
Why is it crashing? And how do I fix it?
Update: That's the entire error message.
2012-07-03 18:28:57.844 appName[3063:11603] (null)
libc++abi.dylib: terminate called throwing an exception
(lldb)
Upvotes: 0
Views: 2372
Reputation: 9039
One problem I see is that your not checking the error object. If an error occurs then queryResults will likely be = nil and you subsequent attempt to check count is going to crash you. At the very least check for the nil condition:
NSMutableArray *queryResults = [[self.appDelegate.managedObjectContext executeFetchRequest:query error:&error] mutableCopy];
if( queryResults == nil ) return; // Or better yet check the value of Error.
Upvotes: 1
Reputation: 35171
Well, no enough debug info... Cause you only need to check whether queryResults
has an object, so I will use
[newItem setValue:[queryResults lastObject] forKey:@"cartThatHasItem"];
instead of
if ([queryResults count] == 1) [newItem setValue:[queryResults objectAtIndex:0] forKey:@"cartThatHasItem"];
Not sure whether it'll solve your issue, but worth trying. :)
Through your question title '... for many-to-many relationship', I wonder what's the relationship between cartThatHasItem
& Cart
? If it is many to one or many to many, then the cartThatHasItem
's data type will be NSSet
. So, you need to wrap the [queryResults objectAtIndex:0]
' like
[newItem setValue:[NSSet setWithObject:[queryResults objectAtIndex:0]]
forKey:@"cartThatHasItem"];
, or you can use
[newItem addCartThatHasItem:[queryResults objectAtIndex:0]]
instead. (addCartThatHasItem:
will be added automatically when you generate your Cart model.)
The Cart model should be like this:
@interface Cart : NSManagedObject
//...
@property (nonatomic, retain) NSSet *cartThatHasItem;
@end
@interface Cart (CoreDataGeneratedAccessors)
//...
- (void)addCartThatHasItemObject:(CartThatHasItem *)value;
- (void)removeCartThatHasItemObject:(CartThatHasItem *)value;
- (void)addCartThatHasItem:(NSSet *)values;
- (void)removeCartThatHasItem:(NSSet *)values;
@end
if you generate your model correctly.
Upvotes: 1