NSPredicate in NSFetchedResultsController throwing EXC_BAD_ACCESS - iphone

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];

Related

how we can search all records using NSPredicate rather than setting fetchController nil?

I am showing all the records in UITableView easily by using:
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Memo" inManagedObjectContext:[appDelegate managedObjectContext]];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"memodate" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[appDelegate managedObjectContext] sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
return _fetchedResultsController;
And for Searching records I am performing this:
- (void)searchBar:(UISearchBar *)aSearchBar textDidChange:(NSString *)searchText {
if (self.searchBar.text ==nil || [self.searchBar.text isEqualToString:#""])
{
self.fetchedResultsController=nil;
}
else
{
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"memodesc CONTAINS[cd] %#", self.searchBar.text];
[_fetchedResultsController.fetchRequest setPredicate:predicate];
}
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
// Handle error
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort(); // Fail
}
[self.tableView reloadData];}
My Question is what is the right way to search all records if searchText value is nil or ""
I am setting self.fetchedResultsController=nil; again for retrieving all the initial results.
But I don't think so this is the right way. It should be doable with predicate ?
Update:
Its working finw with this predicate
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"1=1"];
[_fetchedResultsController.fetchRequest setPredicate:predicate];
But my app is crashing if I used this:
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"All"];
[_fetchedResultsController.fetchRequest setPredicate:predicate];
Unable to parse the format string "ALL"'
And in swift:
let predicate = NSPredicate(value: true)
I know it's an old thread, but anyway...You can also use:
[NSPredicate predicateWithFormat:#"TRUEPREDICATE"];
Predicate format syntax in Apple's documentation
Just set the predicate to nil if you want to fetch all entities.

NSFetchResultsController delegate not getting called

I have the following code:
- (NSFetchedResultsController *)fetchedResultsController {
// Set up the fetched results controller if needed.
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"DiskStory" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"isRemoved == %#", [NSNumber numberWithBool:NO]];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"created" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Set limit
[fetchRequest setFetchBatchSize:25];
// Set batch size
[fetchRequest setFetchLimit:50];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:kSavedStoryCache];
aFetchedResultsController.delegate = self;
fetchedResultsController = aFetchedResultsController;
}
return fetchedResultsController;
}
in my viewDidLoad I have:
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
I was wondering why my :
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
}
delegate, isn't called? I put a break point inside it. Any idea?
I had this problem before, it's not called when you call performFetch for the first time but only when data in fetchedResultsController is actually changed. For instance when you delete object from context that is in this fetch results, delegate will be called.
I think you have used self. at wrong places. Please see the code below; i have added comments to the changes
- (NSFetchedResultsController *)fetchedResultsController {
// Set up the fetched results controller if needed.
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"DiskStory" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"isRemoved == %#", [NSNumber numberWithBool:NO]];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"created" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Set limit
[fetchRequest setFetchBatchSize:25];
// Set batch size
[fetchRequest setFetchLimit:50];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:kSavedStoryCache];
aFetchedResultsController.delegate = self;
fetchedResultsController = aFetchedResultsController; // -> Shouldn't be self.fetchedResultsController
}
return fetchedResultsController; // -> Shouldn't be self.fetchedResultsController
}
Also, if you have synthesize your fetchedResultsController as follows:
fetchedResultsController = _fetchedResultsController
Then in - (NSFetchedResultsController *)fetchedResultsController method you should refer to it as _fetchedResultsController

can't able to delete data in coredata in iphone

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.

perform new fetch in core data iphone

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;

Empty FetchedResultsController in Core Data

I'm using core data and I have an entity defined called LogRecord. Elsewhere this is populated with objects using:
LogRecord *rec = [NSEntityDescription insertNewObjectForEntityForName:#"LogRecord"
inManagedObjectContext:managedObjectContext];
[rec timestampNow];
rec.moodType = [NSNumber numberWithUnsignedInteger:i];
rec.moodValue = value;
NSError *error = nil;
if (![rec.managedObjectContext save:&error]) {
[DataUtil displayFatalError:error message:#"Failed to save log entry"];
errors++;
}
I've checked and the underlying sqlite database has records in it after using this code.
However, when I try to query for the data using this:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController == nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"LogRecord"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"timestamp" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
}
return fetchedResultsController;
}
It comes up empty as evidenced by [[self.fetchedResultsController sections] count] returning zero.
Any idea how I might debug this? It was working before I tried to break this code out into a different UIViewController....
Never mind.... Somehow the call to [[self fetchedResultsController] performFetch:&error] in viewDidLoad got deleted.