fetching particular predicate from database - ios

I have 4 CoreData database. Each actually having their own value. But it is too heavy and i would like to reduce it to 1 Database. So each time i want to pull information from the database, i can choose what to pull. I need to use NSPredicate to set the string that i want to pull izzit?
Do i set my NSPredicate like this?
NSString *value = #"Food";
NSString *wildcardedString = [NSString stringWithFormat:#"%#*", value];
[[NSPredicate predicateWithFormat:#"ANY places.type like %#", wildcardedString];
and how do i bind the NSPredicate with the fetch request sequence?
this is my fetchedResultsController
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil)
{
return fetchedResultsController;
}
CoreDataMelakaAppDelegate *appDelegate = (CoreDataMelakaAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
[fetchRequest setEntity:[NSEntityDescription entityForName:#"WhereTo" inManagedObjectContext:context]];
NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES] autorelease];
NSArray *sortDescriptors = [[[NSArray alloc] initWithObjects:sortDescriptor, nil] autorelease];
[fetchRequest setSortDescriptors:sortDescriptors];
// NSPredicate *pred = [NSPredicate predicateWithFormat:#"(name = %#)", wher.name];
//[fetchRequest setPredicate:pred];
NSString *value = #"Nasi";
NSString *wildcardedString = [NSString stringWithFormat:#"%#*", value];
[[NSPredicate predicateWithFormat:#"ANY wher.name like %#", wildcardedString];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
return fetchedResultsController;
}

When you alter the predicate of a fetch request used by a fetched results controller (FRC), you have to create a new fetched results controller.
Your code is fine logically but it only creates a FRC once with a predicate that compiles to:
ANY wher.name like Nasi*
... each time the FRC executes its fetch, it use that exact predicate.
If you want to use a flexible predicate, you will need to create a new FRC every time you change the predicate.

Related

Objective C: unrecognized selector sent to instance 0x6080000550c0

Here, m try to sort the array when refersh the tableview but is crash the application when refresh tableview.
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[_PFArray
sortUsingDescriptors:]: unrecognized selector sent to instance
0x6080000550c0'
#interface TableViewController () {
NSMutableArray *returnArray;
}
#end
- (void)viewDidAppear:(BOOL)animated {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate manageObjectContext];
NSError *error = nil;
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Resgistration" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
[request setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObjects:#"Unique",nil]];
returnArray = [[NSMutableArray alloc] init];
returnArray = [context executeFetchRequest:request error:&error];
for(Resgistration* reg in returnArray) {
NSLog(#"%#", reg);
NSLog(#"%#", reg.roshan);
}
[self.tableView reloadData];
UIColor *gray = [UIColor colorWithRed:234/255.0 green:234/255.0 blue:234/255.0 alpha:1.0];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Please Wait"];
[refreshControl setBackgroundColor:gray];
[refreshControl addTarget:self action:#selector(sortArray) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
}
- (void)sortArray
{
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES selector:#selector(localizedStandardCompare:)];
NSMutableArray *sortDescriptior = [[NSMutableArray alloc] initWithObjects:sort, nil];
[returnArray sortUsingDescriptors:sortDescriptior]; // crash the app
[self.tableView reloadData];
[self.refreshControl endRefreshing];
}
Please help me to fix this problem. Thank you.
_PFArray is a subclass of NSArray and is immutable. You can use sortUsingDescriptors: on mutable array only, hence the crash.
It looks like somewhere along the code you have assigned instance of CoreData array inside returnArray variable. There you must use mutableCopy method to convert the immutable array to its mutable version, something like this:
returnArray = [<data array fetched from core data> mutableCopy];
Edit after looking at complete code
returnArray = [[context executeFetchRequest:request error:&error] mutableCopy];

NSPredicate between two dates returns 0 results

I am trying to retrieve some results based on the "begin" (NSDate) field. However, it always returns 0 results.
And I can't figure out what I am doing wrong. I am guessing it has something to do with the NSDate type but I have double checked and everything seems correct.
I have checked this answer, and this one also. But to no avail…
Any help would be greatly appreciated.
Here is the definition in the model file :
#property (nonatomic, retain) NSDate * begin;
And here is the code from which I call the fetch Request.
-(void)getCalendarListForDatesFrom:(NSDate *)startDate
To:(NSDate *)endDate
inViews:(NSArray *)daysArray
{
// Reset dates to Midnight
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
NSUInteger preservedComponents = (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit);
startDate = [calendar dateFromComponents:[calendar components:preservedComponents
fromDate:startDate ]
];
endDate = [calendar dateFromComponents:[calendar components:preservedComponents
fromDate:endDate ]
];
NSLog(#"Get Events for dates %# to %#", startDate, endDate);
_isRetrievingData = YES;
NSManagedObjectContext *MOC;
NSPredicate *predicate;
NSError *error = nil;
NSString *entityName = #"CalendarEvent";
//AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
//BOOL doIHaveConnexion = [appDelegate getConnexion];
MOC = self.managedObjectContext;
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName
inManagedObjectContext:MOC ];
// Fetch Request
NSFetchRequest *fetchRequest;
fetchRequest = [[NSFetchRequest alloc] init];
if (!fetchRequest)
{
fetchRequest = [[NSFetchRequest alloc] init];
}
[fetchRequest setEntity:entity];
// Filter
NSLog(#"Filter results between dates %# and %#", startDate, endDate);
predicate = [NSPredicate predicateWithFormat:#"(%K >= %#) AND (%K <= %#)", #"begin", startDate, #"begin", endDate];
//predicate = [NSPredicate predicateWithFormat:#"(%K > %#)", #"begin", [NSDate date]];
NSLog(#"PREDICATE = %#", predicate);
NSLog(#"Set Predicate");
[fetchRequest setPredicate:predicate];
NSLog(#"Set Sort Descriptor");
NSSortDescriptor *beginDateDescriptor = [[NSSortDescriptor alloc] initWithKey:#"begin"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)
];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:beginDateDescriptor, nil];
NSLog(#"Fetch");
[fetchRequest setSortDescriptors:sortDescriptors];
NSLog(#"Init Fetch");
// Initialize Fetched Results Controller
if (!self.fetchedResultsController)
{
self.fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:MOC
sectionNameKeyPath:nil
cacheName:nil ];
}
NSLog(#"Perform Fetch");
// Perform Fetch
[self.fetchedResultsController performFetch:&error];
NSArray *calEvents = [MOC executeFetchRequest:fetchRequest error:&error];
currentCalEvents = [calEvents mutableCopy];
if (error)
{
NSLog(#"Unable to execute fetch request.");
NSLog(#"%#, %#", error, error.localizedDescription);
}
else
{
NSLog(#"TOTAL CALENDAR EVENTS %lu",(unsigned long)[calEvents count]);
NSLog(#"currentCalEvents = %#", currentCalEvents);
[self addCalendarEventsToDays: daysArray];
}
fetchRequest = nil;
}
Here are the logs from the console :
Filter results between dates 2015-01-02 23:00:00 +0000 and 2015-01-07 23:00:00 +0000
PREDICATE = begin >= CAST(441932400.000000, "NSDate") AND begin <= CAST(442364400.000000, "NSDate")
Set Predicate
Set Sort Descriptor
Fetch
Init Fetch
Perform Fetch
TOTAL CALENDAR EVENTS 0

Fetching data from core data using GCD causes issue IOS

Hi I am developing IOS application in which I am using core data. In my application I am using split view controller. So my split view controller's master view contains following things:
-(void) viewWillAppear:(BOOL)animated
{
[self getNotificationCounter];
[self getTicketCounter];
}
-(void) getNotificationCounter:(UITableViewCell *) cell
{
dispatch_queue_t myQueue = dispatch_queue_create("My Notification Queue",NULL);
dispatch_async(myQueue, ^{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"NotificationsData" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; dispatch_async(dispatch_get_main_queue(), ^{
//update view;
});
});
}
-(void) getTicketCounter:(UITableViewCell *) cell
{
dispatch_queue_t myQueue = dispatch_queue_create("My Ticket Queue",NULL);
dispatch_async(myQueue, ^{
NSFetchRequest *ticketFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *ticketEntity = [NSEntityDescription
entityForName:#"Tickets" inManagedObjectContext:context];
[ticketFetchRequest setEntity:ticketEntity];
NSError *ticketError = nil;
NSArray *ticketFetchedObjects = [context executeFetchRequest:ticketFetchRequest error:&ticketError];
dispatch_async(dispatch_get_main_queue(), ^{
// update view
});
});
}
and detail view controller have following thing.
- (NSFetchedResultsController *)fetchedResultsController {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#“channels” inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"channelId" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
So my problem is like this :
In my detail view controller I have one NSFetchRequestController and in master view have two
two NSFetchRequest with two GCD. if I start my application in portrait mode its works fine. But in landscape mode it stops without giving any error. Another thing If remove one GCD NSFetchRequest from master controller it works fine Or if I remove NSFetechResultController then also it works fine. Why it is so? Am I doing some thing wrong. Need Some help. Thank you.
You may not let NSManagedObjectContext or NSManagedObject cross threads.
You must create a fresh context for your thread.
dispatch_queue_t myQueue = dispatch_queue_create("My Ticket Queue",NULL);
dispatch_async(myQueue, ^{
NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] init];
threadContext.parent = context; //assumes other context is NSMainThreadConcurrencyType
NSFetchRequest *ticketFetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *ticketEntity = [NSEntityDescription
entityForName:#"Tickets" inManagedObjectContext:threadContext];
[ticketFetchRequest setEntity:ticketEntity];
...
To get NSManagedObject between contexts use it's objectID property and [NSManagedObjectContext objectWithId:]
Should you make edits then you will need to save the thread context. Those changes will propagate automatically down to the parent context.
Otherwise you discard the context at the end of the block like a sheet of paper.
EDIT
Also if the count of the objects is the only thing you want then you can use
countForFetchRequest:error: on NSManagedObjectContext
This will be a cheaper call because no objects are created for you.

Core data objects update through loop

I have a tableView showing core-data objects. On the same view there are five buttons. Each button action should update the value of an attribute from the objects.
As an example, I will show you what I have to update the attribute 'isDone':
- (IBAction)allDoneAction:(id)sender {
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
int i=0;
for (NSManagedObject *mo in context)
{
[mo setValue:#"Done" forKey:#"isDone"];i++;
}
[managedObjectContext save:nil];
}
This method throws following following exception:
NSManagedObjectContext countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x9a6b0a0
2014-01-06 19:01:43.862 To-Do Pro[679:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObjectContext countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x9a6b0a0'
What do I need to avoid the exception and obtain the desired update?
Here is my NSFetchedResultsController:
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController) return fetchedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity =
[NSEntityDescription entityForName:#"FavoriteThing"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"displayOrder"
ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]
initWithObjects:sortDescriptor, nil];
//SOLO TO-DOS DE TODAY
todayDate = [NSDate date];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:todayDate]; // Get necessary date components
NSNumber *yearBuscado = [NSNumber numberWithLong:[components year]];
NSNumber *mesBuscado = [NSNumber numberWithLong:[components month]];
NSNumber *diaBuscado = [NSNumber numberWithLong:[components day]];
// NSString *tipourgente = #"Urgent";
// NSString *tipocolor = #"Yellow";
NSString *textoNotDone = #"Not done";
NSString *textoNotDeleted = #"Not deleted";
NSPredicate *yearPredicate = [NSPredicate predicateWithFormat:#"todoYear == %#", yearBuscado];
NSPredicate *monthPredicate = [NSPredicate predicateWithFormat:#"todoMonth == %#", mesBuscado];
NSPredicate *dayPredicate = [NSPredicate predicateWithFormat:#"todoDay == %#", diaBuscado];
NSPredicate *notDonePredicate = [NSPredicate predicateWithFormat:#"isDone== %#", textoNotDone];
NSPredicate *notDeletedPredicate = [NSPredicate predicateWithFormat:#"isSemiDeleted==%#", textoNotDeleted];
// NSPredicate *urgentPredicate = [NSPredicate predicateWithFormat:#"urgent == %#", tipourgente];
// NSPredicate *colorPredicate = [NSPredicate predicateWithFormat:#"color == %#", tipocolor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSPredicate *busqueda = [NSCompoundPredicate andPredicateWithSubpredicates:#[yearPredicate,monthPredicate,dayPredicate,notDonePredicate,notDeletedPredicate]];
[fetchRequest setPredicate:busqueda];
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil cacheName:nil];
aFetchedResultsController.delegate = self;
[self setFetchedResultsController:aFetchedResultsController];
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}
Ok, I know absolutely nothing about core data, but from what I have researched in the last two minutes it appears as though you do not loop over An object of NSManagedObjectContext. You need to create a search within the context and get the results from that. Then iterate through the results and modify willy nilly.
Here is an example taken from this answer:
NSManagedObjectContext * context = [self managedObjectContext];
NSFetchRequest * fetch = [[[NSFetchRequest alloc] init] autorelease];
[fetch setEntity:[NSEntityDescription entityForName:#"ShoppingBasket" inManagedObjectContext:context]];
NSArray * result = [context executeFetchRequest:fetch error:nil];
for (id basket in result)
[context deleteObject:basket];
So get the context, Create a search, get an array from the context based on the search criteria, loop through the results and do as you will with updating them.
If you are using a fetchedResultsController already to populate the tableView then you can iterate over the objects in the fetchedResultsController like this:
- (IBAction)allDoneAction:(id)sender {
NSArray *objects = [fetchedResultsController fetchedObjects];
for (NSManagedObject *mo in objects) {
[mo setValue:#"Done" forKey:#"isDone"];i++;
}
NSError *error;
bool result = [[fetchedResultsController managedObjectContext] save:&error];
if (!result) {
NSLog(#" error saving context, %#, %#", error, error.userInfo);
}
}
BTW you should be checking for errors in your call to save so don't pass in nil.

Load CoreData objects' string property into UIPickerView

Currently I have an entity named "Events" in a CoreData app. "Events" has one string property named "eventName".
In the -(void)viewDidLoad I am trying to Fetch all the "Events" objects and load their "eventName" by alphabetical order into a UIPickerView.
The ultimate end goal is through the use of a textField, buttons and the pickerView being add new objects in and remove unwanted objects out. Basically turning the UIPickerView into a UITableView. Currently I am able to save objects to the CoreData store, but am not able to pull them/their properties out into the UIPickerView.
I am willing and able to share the project source code to anyone who wants it, or is willing to look at it to help out.
thanks
Chris
-(void)update
{
NSMutableArray *array2 = [[NSMutableArray alloc] init];
CDPickerAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *moc = [appDelegate managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Event" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"callName" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
NSArray *array = [moc executeFetchRequest:request error:&error];
for (int i=0; i<array.count; i++) {
Event *theEvent = [array objectAtIndex:i];
NSString *StringOne = [NSString stringWithFormat:#"%#",theEvent.callName];
[array2 addObject:StringOne];
}
self.pickerData = array2;
[singlePicker reloadAllComponents];
}
-(IBAction)addCall{
CDPickerAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *theEvent = [NSEntityDescription insertNewObjectForEntityForName:#"Event" inManagedObjectContext:context];
[theEvent setValue:callField.text forKey:#"callName"];
[context save:&error];
callField.text=#"";
[callField resignFirstResponder];
self.update;
}

Resources