Why do I get a NSInvalidArgumentException? - objective-c

Why do I get a NSInvalidArgumentException with my code below?
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Order dish]: unrecognized selector sent to instance
(void)fetchDishRecords: (NSMutableArray*)array predicate: (NSString*)categoryname
{
// Define our table/entity to use
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Order" inManagedObjectContext:managedObjectContext];
// Setup the fetch request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
//set predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"Category=%#", categoryname];
[request setPredicate:predicate];
//set sorting
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Dish" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
// Fetch the records and handle an error
NSError *error;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (!mutableFetchResults)
{
// Handle the error.
}
else
{
for(int i=0;i<[mutableFetchResults count];i++)
{
Order *orderObj = [mutableFetchResults objectAtIndex:i];
//NSLog(orderObj.dish);
//NSString* tempStr = orderObj.dish;
[array addObject:orderObj.dish];
}
}
// Save our fetched data to an array
[mutableFetchResults release];
[request release];

[array addObject:orderObj.dish];
Seems to be the culprit...
orderObj is of class Order and the error says it cannot perform selector dish.
Make sure you have a method -(void)dish implemented for your Order class.

Related

Core Data crash: Keypath Project not found in entity

- (void)fetchResult
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"Project" ascending:YES];
[request setEntity:self.entityDescription];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
self.fetchResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
NSError *fetchError = nil;
BOOL success = [self.fetchResultController performFetch:&fetchError];
if (success) {
NSLog(#"fetched!");
}
else {
NSLog(#"fetch fail!");
}
}
The entityDescription and the context is set in the viewDidLoad method, as it is shown below:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = appDelegate.managedObjectContext;
self.entityDescription = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:self.managedObjectContext];
Crash info:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath Project not found in entity '
Could anybody give a hand?;)
The key used in the sort descriptor
[NSSortDescriptor sortDescriptorWithKey:#"Project" ascending:YES];
must be a property of your Core Data entity, not the name of the entity itself.
So you should replace #"Project" in the sort descriptor by some property of
the Project entity, such as #"name".
It is not related to the initial question, but it is highly related to the title of the question.
And as it was the only one I've found for this topic, it may be useful for someone else:
So, I've got "Core Data crash: 'keypath Videos not found in entity ...'" because I've used string interpolation in a predicate:
let projectName = "Videos"
let predicate = NSPredicate(format: "\(#keyPath(Scene.relatedProject.name)) == \(projectName)")
The correct way is:
let projectName = "Videos"
let predicate = NSPredicate(format: "\(#keyPath(Scene.relatedProject.name)) == %#", projectName)
Hope, it will save someone hour(s) of figuring out what is going on.
make sure you are using below syntax for your Query
Example:
fetchRequest.predicate = NSPredicate(format: "username = %#", userName)
where username is the key and userName is variable to hold any name in the example.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setPredicate:predicate];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Project" inManagedObjectContext:context];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"Column_Name" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *arrTemp = [context executeFetchRequest:fetchRequest error:&error];
if([arrTemp count]>0){
NSLog(#"%#",arrTemp);
}
Set cache name like:
self.fetchResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"temp"];

to set default value when core data fetch result is null

I am using simple core data fetch request code.
- (NSMutableArray *) read_cd
{
NSError *error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"List_CD" inManagedObjectContext:cd_Context];
[request setEntity:entity];
NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:#"last_date" ascending:NO];
NSArray *sortDescriptor = [[NSArray alloc] initWithObjects:sd, nil];
[request setSortDescriptors:sortDescriptor];
NSMutableArray *mutableFetchResults = [[cd_Context executeFetchRequest:request error:&error] mutableCopy];
if(mutableFetchResults == nil){
//Handle the error
}
return mutableFetchResults;
}
and I'm using return value like this
MSMutableArray *now_cd = self.read_cd;
cell output for {
cell.label1.text = [[now_cd objectAtIndex:i] cd_title];
cell.label2.text = [[now_cd objectAtIndex:i] cd_auth];
}
I want to set default value when executeFetchRequest is null.
so I can continue to use an existing output module.
I don't know how to make a method like that
[[object objectAtIndex:i] instance]

iOS: How to Sort with NSSortDescriptor a value from relationship?

I have two objects with a relationship in my Data Model...
Person {Name, position, Title}
Position {position, PositionSort}
Each of the above have their own class files (subclasses of NSManagedObject). I'm trying to sort by PositionSort above. I can currently sort by Position by using the following code.
NSSortDescriptor *sortDescriptorPosition = [[NSSortDescriptor alloc] initWithKey:#"position" ascending:YES];
I am unsure though how I'm able to access and use the PositionSort. Any ideas? Thanks!
UPDATE: Added full function...
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil) {
return __fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Person" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptorState = [[NSSortDescriptor alloc] initWithKey:#"position.positionSort" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptorState, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:#"(companyID == %#)", company.companyID];
[fetchRequest setPredicate:searchPredicate];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"position.positionDescription" cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __fetchedResultsController;
}
With the above code I'm getting the following error at Runtime.
2012-08-12 10:29:45.499 College[269:707] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0xd6bd310> valueForUndefinedKey:]: this class is not key value coding-compliant for the key positionDescription.'
I'm not sure you want to sort exactly, but the following NSSortDescriptor can be used to sort the Person objects using the PositionSort value.
NSSortDescriptor *sortDescriptorPosition = [[NSSortDescriptor alloc] initWithKey:#"position.PositionSort" ascending:YES];
perhaps, you looked for this...

Fetching a maximum value with CoreData

This is the first time I'm trying to use CoreData and I'm having some trouble getting the max date from a a table.
This is basically what I'm trying to do:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Radar" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:#"modifiedOn"];
NSExpression *maxDate = [NSExpression expressionForFunction:#"max:" arguments:[NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:#"maxDate"];
[expressionDescription setExpression:maxDate];
[expressionDescription setExpressionResultType:NSDateAttributeType];
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
NSError *error = nil;
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
if (objects == nil) {
// Handle the error.
}
else {
if ([objects count] > 0) {
NSLog(#"%d", [objects count]);
NSLog(#"MAx date: %#", [[objects objectAtIndex:0] valueForKey:#"modifiedOn"]);
}
}
This code somehow does the opposite of what I want and print the minimum date. Since I've just started with CoreData it's obvious that I got something wrong, but what?
Maybe you should try to NSLog the [objects lastObject],instead of first one?

NSSortDescriptor for NSFetchRequest sorting unexpectedly

My entity has a property (sortOrder) that is of the type Decimal(NSDecimalNumber) but when I execute a fetch request using that property as a key, I get back results in a seemingly random order. If I output the value of the property I get really strange values until I get it's intValue.
Example: The first run produces this result. The first value is the raw value of the property. The second is the intValue, the actual value of the property when I created the object - or at least I thought.
85438160 10
74691424 20
Second run...
85333744 10
85339168 20
Third...
85263696 20
85269568 10
What the hell?
Fetch Request:
NSMutableArray *cats = [[NSMutableArray alloc] initWithArray:[CoreDataHelper searchObjectsInContext:#"RestaurantMenuCategory":nil:#"sortOrder":YES:NO:nil]];
Here is the searchObjectsInContext method from my CoreDataHelperClass:
+(NSMutableArray *) searchObjectsInContext: (NSString*)entityName : (NSPredicate *)predicate : (NSString*)sortKey : (BOOL)sortAscending : (BOOL)distinct : (NSString*)distinctProperty
{
RestaurantController *ctrl = [RestaurantController sharedRestaurantController];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:ctrl.managedObjectContext];
[request setEntity:entity];
if(distinct==YES){
[request setReturnsDistinctResults:YES];
}
if(distinctProperty!= nil){
[request setPropertiesToFetch :[NSArray arrayWithObjects:distinctProperty,nil]];
}
if(predicate != nil){
[request setPredicate:predicate];
}
if(sortKey != nil){
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
}
NSError *error;
NSMutableArray *mutableFetchResults = [[[ctrl.managedObjectContext executeFetchRequest:request error:&error] mutableCopy] autorelease];
[request release];
return mutableFetchResults;
}
You cannot use a %d format to print out an NSDecimalNumber.
NSDecimalNumber is an Objective-C object; %d is for printing "int"s. If you use the %d format string, it will probably print something non-useful like the address of the object; use "%#" instead.