NSPredicate creation with CoreData for an equal object - objective-c

I have a strong pointer with the name "sensor" to an object of the class "SensorDB".
I tried to create a NSFetchedResultController so that my UIViewController gets notified, if something changes inside the "sensor" object.
To get the desired object into my NSFetchedResultController, I created following NSPredicate:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self == %#", self.sensor];
The goal is, that I have just one object in the NSFetchedResultController and get notifications about any updates, so that I can update my GUI.
But if I run my application, the app crashes when I try to alloc and init the NSFetchedResultController.
Here's my NSFetchedResultController code:
- (NSFetchedResultsController *)fetchedResultsControllerSensor
{
if (_fetchedResultsControllerSensor != nil) {
return _fetchedResultsControllerSensor;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"SensorDB" inManagedObjectContext:dbHandler.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self == %#", self.sensor];
[fetchRequest setPredicate:predicate];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:dbHandler.managedObjectContext sectionNameKeyPath:nil cacheName:#"SensorCache"];
self.fetchedResultsControllerSensor = theFetchedResultsController;
_fetchedResultsControllerSensor.delegate = self;
return _fetchedResultsControllerSensor;
}
Thank you for your help or another/better approach
Linard

I thought, that I don't need a sort descriptor, because I've just one result object, but it looks like that the initialization of a NSFetchedResultController crashes, if there isn't at least one NSSortDescriptor.
That's now my NSPredicate and NSSortDescriptor:
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"(SELF = %#)", self.sensor];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"displayOrder" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

Related

Error while fetching data from Core Data

I’m working on an dictionary app. this app using core data and I'm very new to core data. In the database, records stored with a single entity called dictionary and dictionary entity has just two attributes “English” & “Meaning”.
So whenever user types some char say a, in UISearchBar, I want to fetch records from data base that starts from “a”, if user types data a than b that I want to fetch records starts from “ab” and so on.
I’m trying same thing by below code:
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:ENTITY_NAME inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// retrive the objects with a given value for a certain property
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K beginswith[c] %#",#"English",searchText];
[request setPredicate:predicate];
// Edit the sort key as appropriate.
/*NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"English" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];*/
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
/*NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;*/
NSError *error = nil;
_searchResult = [managedObjectContext executeFetchRequest:request error:&error];
when this code executes my app crashes with the following error msg:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath English not found in entity <NSSQLEntity TamilEnglishDict id=1>'
EDIT:
this is how my Data Model is...
Any who can guide me to the right path of fetching records properly?
Yes it's case sensitive.
So the correct predicate is the following.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K beginswith[c] %#",#"english", searchText];
or just
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"english beginswith[c] %#", searchText];
but while saving those values in managedObject I wrote '[managedObject
setValue:[obj objectForKey:#"English"] forKey:#"English"]';
So now edit your question and explain me the comment above. What do you mean?
Maybe you could just do
[managedObject setValue:[obj objectForKey:#"English"] forKey:#"english"];
I saw your code & your code is correct, you just have to change Predicate you are using. just replace this code with your predicate & hope your problem is solve. because you want result that conatain "ab" or "a" or "b" so you have to use "contain" in place of "beginswith".
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K contains[cd] %#",#"English", searchText];
Let me know if you have any issue.

Using an NSPredicate to access self.items

For various reasons (summarized at the end) I am experimenting with using an NSFetchedResultsController to return some NSManagedObjects.
Specifically, a Person has many Cars, modeled using the core data relationship cars. I want to add another method to Person to return the same cars as self.cars, but using a FRC.
I think I am making a basic error with my NSPredicate, which is designed to only find the cars where car.person == self:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Car"];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"dateAdded" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"person == '%#'", self];
[fetchRequest setPredicate:predicate];
NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
NSError *error;
BOOL success = [controller performFetch:&error];
No cars are being returned at all. Is my predicate incorrect?
Side Note - why not just use self.cars?
Like I say this is an experiment. I am hoping to benefit from the persistent cache of an NSFetchedResultsController.
The single quotes in the predicate are wrong, it should be
[NSPredicate predicateWithFormat:#"person == %#", self];
In the example you are fetching "Person" objects. Maybe you want to fetch "Car" objects instead?
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Car"];

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...

Detect updates on sectionNameKeyPath from NSFetchedResultsController

Here is the case. I have 2 models:
Sport (with attribute name and relationShip players)
Player (with attribute name and relationShip sport)
In a ViewController, I wan't to display all players in a UITableView ordered by sport.
When a player name changes, NSFetchedResultsControllerDelegate callbacks are called.
But when the name of a Sport is updated, no NSFetchedResultsControllerDelegate callbacks are called.
Is this a normal behaviour ? How can I know the updates of Sport.name (without creating another NSFetchedResultsController) ?
Thank you and Best Regards.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"sport.name != NULL"];
[fetchRequest setPredicate:predicate];
NSArray *sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"sport.name" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES],
nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Player"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityDescription];
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:#"sport.name"
cacheName:nil];
[fetchRequest release];
fetchedResultsController.delegate = self;
NSError *error = nil;
if ([fetchedResultsController performFetch:&error] == NO) {
ALog(#"Fetch error: %#", [error localizedDescription]);
}
You can using a tip:
If (fetchresultcontroller != nil || isOtherEnthityUpdate)
{
return fetchresultcontroller;
}
And do self.tableview reload from any place where u check other entity. It can be notification center or other tableview.

Core Data: keypath name not found in entity

I'm crashing with this message :
'NSInvalidArgumentException', reason: 'keypath name not found in entity
Obvisouly I'm not querying my entity correctly .
//fetching Data
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Viewer" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSString *attributeName = #"dF";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name like %#",attributeName];
[fetchRequest setPredicate:predicate];
NSLog(#"predicate : %#",predicate);
NSError *error;
NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
NSLog(#"items : %#",items);
[fetchRequest release];
//end of fetch
And here is my data Model:
I want to return the value of "dF", shouldn't call it like this ? :
NSString *attributeName = #"dF";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name like %#",attributeName];
If you want to get value from your dF property, you have to fetch an array of NSManagedObjects and then use [fetchedManagedObject valueForKey:#"dF"]; to get your value.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Viewer" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *items = [context executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
NSManagedObject *mo = [items objectAtIndex:0]; // assuming that array is not empty
id value = [mo valueForKey:#"dF"];
Predicates are used to get array of NSManagedObjects that satisfy your criteria. E.g. if your dF is a number, you can create predicate like "dF > 100", then your fetch request will return an array with NSManagedObjects that will have dF values that > 100. But if you want to get just values, you don't need any predicate.
I was using a NSSortDescriptor initialized with a String key:
let fetchRequest = NSFetchRequest<SomeManagedObject>(entityName: "SomeManagedObject")
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
I then changed the name of the name attribute in the model. Refactored all of the property names, but didn't catch the stringly typed key: "name".
The solution for Swift is to use NSSortDescriptor(keyPath: instead, which will fail to compile if the property key path changes.
NSSortDescriptor(keyPath: \SomeManagedObject.firstName, ascending: true)