Okay I have a one-to-many relationship in core data. A Meal can consists of many different Food. My code doesn't quite seem to be working in the Fetch Controller. I can say this with confidence, the self.meal is the current Meal I am trying to fetch. I am sharing the context through out the application.
The problem I am having is that the application is displaying foods but it doesn't quite seem to match up against what should be inside of a Meal. As soon as I add a food, it immediately displays that, even if it is not inside of the Meal.
Any help or suggestion, I am doing this fetch correctly.
- (NSFetchedResultsController *)fetchedResultsController
{
self.context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Food" inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
NSPredicate *foodPredicate = [NSPredicate predicateWithFormat:#"meals == %#", self.meal];
[fetchRequest setPredicate:foodPredicate];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.context sectionNameKeyPath:nil cacheName:#"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
[fetchRequest release];
[theFetchedResultsController release];
return _fetchedResultsController;
}
If self.meals were nil then the NSFetchedResultsController would return Foods that are not part of a Meal, thereby accounting for the behavior you're noticing.
Your predicate is incorrect. You should not be comparing meals, which is a NSSet of Meal objects, to a single meal. You need to see if the meals set on the Food object contains that meal.
[NSPredicate predicateWithFormat:#"%# in meals", self.meal]
Related
I have a UITableViewController using an NSFetchedResultsController. If I remove the predicate, It works fine, but with the predicate, it throws bad access (EXC_BAD_ACCESS). I enabled NSZombieEnabled, but that turned up nothing. I'm using ARC. I don't get it! Please help. Here's my fetchedresultscontroller code NOTE: Changing my predicate to random simple predicates such as "unitNumber = nil" or "unitNumber LIKE %#", unString STILL CAUSES a crash, however commenting the predicate out entirely will not produce crash (But then I have all objects and no filter obviously):
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Unit" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"workTicket.appointment.scheduleRowPointer = %#", rp];
[self.fetchedResultsController.fetchRequest setPredicate:predicate];
// Sort Descriptor
NSSortDescriptor *unitNumberDescriptor = [[NSSortDescriptor alloc] initWithKey:#"unitNumber" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:unitNumberDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"addedToTicket" cacheName:nil];
return _fetchedResultsController;
}
Change:
[self.fetchedResultsController.fetchRequest setPredicate:predicate];
to :
[fetchRequest setPredicate:predicate];
After [managedObjectContext deleteObject:device]; still showing data in device object.can't delete the data from database.how can i delete the data
if (managedObjectContext == nil)
{
managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSLog(#"After managedObjectContext: %#", managedObjectContext);
}
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Reserve" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// NSSortDescriptor tells defines how to sort the fetched results
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"number" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSLog(#"sort count%d",[sortDescriptors count]);
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(number = %d)", [sender tag]];
// [fetchRequest setPredicate:predicate];
[fetchedResultsController.fetchRequest setPredicate:predicate];
self.fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSLog(#"Count of array::::%d",[fetchedObjects count]);
NSManagedObject *device = [fetchedObjects lastObject];
NSLog(#"device::::%#",device);
[managedObjectContext deleteObject:device];
NSLog(#"device::::%#",[fetchedObjects lastObject]);
thanks in advance
Deleting the object (device) from the context will not cause it to automatically disappear off the end of the previous result-set (fetchedObjects). The array that you fetch will contain whatever objects existed at the time it was fetched. It does not update itself automatically.
Have you tried running your fetch request again after deleting the object from the context and then checking to see if the device still appears in the result-set? Also, if you really want the object to stay deleted, it's a good idea to save your context as well.
If you want, you can add a delegate to the NSFetchedResultsController, which will call back into your code whenever the result-set changes. You can then use the notification as a cue to reload the array.
I have these objects that are unique except for two columns once of which I am using as the display in the UITableView. The UITableView will often show duplicates due to this. I need to filter out these duplicates somehow.
Setting distinctResult on the FetchResult won't work in this case since that limits the functionality of the NSFetchedResultsController and it requires that the REsultType be a NSDictionary instead of a subclass of managed object.
Doesn't anyone have any idea how I can filter these duplicates out using a predicate?? Remember that every field on these objects is unique except for two of them.
-(NSFetchedResultsController *) fetchGroupedObjects:(NSString *)entityDescription
sortField:(NSString *)sortField
withPredicate:(NSPredicate *)predicate {
BPRAppDelegate *delegate = (BPRAppDelegate *)[UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = delegate.managedObjectContext;
//NSError *error;
//Fetch the data....
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:entityDescription inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *groupDescription = [[NSSortDescriptor alloc]
initWithKey:GROUP_NAME ascending:YES];
//Sort by Category Name
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:sortField ascending:YES];
NSMutableArray *sorts = [[[NSMutableArray alloc] init] autorelease];
[sorts addObject:sortDescriptor];
[sorts addObject:groupDescription];
[fetchRequest setSortDescriptors:sorts];
//[fetchRequest setResultType:NSDictionaryResultType];
//[fetchRequest setPropertiesToGroupBy:[entity.propertiesByName valueForKey:CONTRACTOR_NAME];
if (predicate != nil)
[fetchRequest setPredicate:predicate];
//NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
//NSFetchResultsController
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *fetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context sectionNameKeyPath:GROUP_NAME
cacheName:nil]; //Don't use a cache
[fetchRequest release];
[sortDescriptor release];
[groupDescription release];
return fetchedResultsController; //You can't autorelease this thing... the requestor must do that.
}
While it might be easier to set up an optional to-one relationship back to itself (say, "child") so that you can then fetch with a NSPredicate where "child == nil", you can certainly post-filter easily enough in pure objective C using [array enumerateObjectsUsingBlock:] or equivalent, and only add unique objects per your criteria to the resultant array.
I am doing core data fetches using the standard code provided by Apple, it has the following statement in the beginning of the fetch method.
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController_ != nil) {
return fetchedResultsController_;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:self.entityName inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:self.sortFieldName ascending:YES];
NSMutableArray *sortDescriptors = [[NSMutableArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
if(predicate != nil)
[fetchRequest setPredicate:predicate];
// 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:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:sectionKeyName cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
aFetchedResultsController = nil;
[fetchRequest release];
fetchRequest = nil;
[sortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![fetchedResultsController_ performFetch:&error]) {
}
return fetchedResultsController_;
}
The first time, fetchedResultsController gets the required info. But I am setting a predicate on this result after that. So, I would like the fetch to consider my predicate the next time. If it goes in the above code, it will come out immediately because the old value is not nil.
To overcome this, after setting the predicate, I do
fetchedResultsController_ = nil;
This works ok,but is giving leaks at the fetchedResultsController as soon as the fetchRequest is allocated.
Is there a better way to re-execute the fetch or to avoid the leak?
Just add a release.
if(fetchedResultsController_){
[fetchedResultsController_ release];
}
fetchedResultsController_ = nil;
My object graph is simple.
I've a feedentry object that stores info about RSS feeds and a relationship called Tag that links to "TagValues" object. Both the relation (to and inverse) are to-many. i.e, a feed can have multiple tags and a tag can be associated to multiple feeds.
I referred to How to do Core Data queries through a relationship? and created a NSFetchRequest. But when fetch data, I get an exception stating,
NSInvalidArgumentException
unimplemented SQL generation for predicate
What should I do? I'm a newbie to core data :( I know I've done something terribly wrong... Please help...
Thanks
--
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"FeedEntry" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"authorname" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSEntityDescription *tagEntity = [NSEntityDescription entityForName:#"TagValues" inManagedObjectContext:self.managedObjectContext];
NSPredicate *tagPredicate = [NSPredicate predicateWithFormat:#"tagName LIKE[c] 'nyt'"];
NSFetchRequest *tagRequest = [[NSFetchRequest alloc] init];
[tagRequest setEntity:tagEntity];
[tagRequest setPredicate:tagPredicate];
NSError *error = nil;
NSArray* predicates = [self.managedObjectContext executeFetchRequest:tagRequest error:&error];
TagValues *tv = (TagValues*) [predicates objectAtIndex:0];
NSLog(tv.tagName); // it is nyt here...
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"tag IN %#", predicates];
[fetchRequest setPredicate:predicate];
// 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:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
--
The key here is "ANY"
Example from apple:
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"ANY employees.firstName like 'Matthew'"];
http://developer.apple.com/mac/library/documentation/cocoa/conceptual/CoreData/Articles/cdBindings.html
Do you require SQLite? I am grappling with a similar issue, and have found that everything works as expected with a binary store.
There are limitations when using SQLite as a store, though I have not yet found a document that lists the limitations, only that they exist.
Sorry I can't be of more help.