NSPredicate between two dates returns 0 results - ios

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

Related

Error saving data in Core Data (IOS)

My program receives the JSON data from the Web service. Next, the program stores the data in the database using Core Data. If I call the save data after adding each entry, everything works, but very slowly. Keeping 200 entries takes more than one minute.
If I execute saving only once at the end – the program throw exception.
- (void) onLoadMessages:(NSObject*)object {
NSArray *messages = (NSArray*)object;
if (messages==nil) {
[self onError:#"Message array is null"];
return;
}
NSDate *date = [NSDate date];
long now = [date timeIntervalSince1970];
Boolean update = false;
for(int i=0; i<messages.count; i++) {
NSDictionary *m = messages[i];
Message *msg = [[Message alloc]initWithDictionary:m];
if ([self UpdateMessage:msg UpdateTime:now])
update = true;
}
if (update) {
NSError *error = nil;
// Error throw here
if (![self.managedObjectContext save:&error])
[self onError2:error];
}
}
- (Boolean) UpdateMessage:(Message*) msg UpdateTime:(long)now {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Messages" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSString *s = [NSString stringWithFormat:#"%ld", msg.id];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(id=%#)", s];
[fetchRequest setPredicate:pred];
NSError *error;
NSArray *object = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
Boolean result = false;
if (object==nil)
[self onError2:error];
else {
NSManagedObject *m;
if ([object count]==0) {
// Insert new message
m = [NSEntityDescription insertNewObjectForEntityForName:#"Messages"
inManagedObjectContext:self.managedObjectContext];
[m setValue:[NSNumber numberWithLong:msg.id] forKey:#"id"];
[m setValue:[NSNumber numberWithLong:msg.agancy.id] forKey:#"agancy"];
[m setValue:msg.header forKey:#"header"];
[m setValue:msg.keywords forKey:#"keywords"];
[m setValue:[NSNumber numberWithLong:msg.indate] forKey:#"indate"];
[m setValue:[NSNumber numberWithLong:now] forKey:#"updated"];
result = true;
} else {
// Update message
m = [object objectAtIndex:0];
[m setValue:[NSNumber numberWithLong:now] forKey:#"updated"];
}
// Save the context.
// Too long execution
/*NSError *error = nil;
if (![self.managedObjectContext save:&error])
[self onError2:error];*/
}
return result;
}
Help correct the behavior of the program.
With respect,
Alexander.
P.S.
Execution takes place in the main thread.
Field "Id" for table "Messages" indexed.
I solve the problem by adding privateObjectContext!
_privateObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
And replace managedObjectContext on privateObjectContext when updating/inserting data/

NSFetchedResultsController: ReOrder Sections

I'm following the example from Apple to setup my sections:
https://developer.apple.com/library/ios/samplecode/DateSectionTitles/Listings/DateSectionTitles_APLEvent_m.html
My sections currently appear in the following order:
Section 0: "Upcoming"
Section 1: "Today"
Section 2: "Past"
Code I use in my NSManagedObject .m file:
#pragma mark - Transient properties
- (NSString *)sectionIdentifier
{
// Create and cache the section identifier on demand.
[self willAccessValueForKey:#"sectionIdentifier"];
NSString *tmp = [self primitiveSectionIdentifier];
[self didAccessValueForKey:#"sectionIdentifier"];
if (!tmp)
{
NSDate *dateToCompare = [self getUTCFormateDate:[self startDate]];
NSLog(#"********Date To Compare****** %#", dateToCompare);
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate* now = [NSDate date];
NSDateFormatter *format = [[NSDateFormatter alloc] init];
format.dateFormat = #"dd-MM-yyyy";
NSString *stringDate = [format stringFromDate:now];
NSDate *todaysDate = [format dateFromString:stringDate];
NSInteger differenceInDays =
[calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit forDate:dateToCompare] -
[calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit forDate:todaysDate];
NSString *sectionString;
if (differenceInDays == 0)
{
sectionString = kSectionIDToday;
}
else if (differenceInDays < 0)
{
sectionString = kSectionIDPast;
}
else if (differenceInDays > 0)
{
sectionString = kSectionIDUpcoming;
}
tmp = sectionString;
[self setPrimitiveSectionIdentifier:tmp];
}
return tmp;
}
-(NSDate *)getUTCFormateDate:(NSDate *)localDate
{
NSDateFormatter *dateFormatter;
if (!dateFormatter)
{
dateFormatter = [[NSDateFormatter alloc] init];
}
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
NSString *dateString = [dateFormatter stringFromDate:localDate];
NSDate *dateFromString = [[NSDate alloc] init];
dateFromString = [dateFormatter dateFromString:dateString];
return dateFromString;
}
#pragma mark - Time stamp setter
- (void)setStartDate:(NSDate *)newDate
{
// If the time stamp changes, the section identifier become invalid.
[self willChangeValueForKey:#"startDate"];
[self setPrimitiveStartDate:newDate];
[self didChangeValueForKey:#"startDate"];
[self setPrimitiveSectionIdentifier:nil];
}
#pragma mark - Key path dependencies
+ (NSSet *)keyPathsForValuesAffectingSectionIdentifier
{
// If the value of timeStamp changes, the section identifier may change as well.
return [NSSet setWithObject:#"startDate"];
}
In my tableViewController, I setup the NSFetchedResults as following:
- (NSFetchedResultsController *)fetchedResultsController
{
if(_fetchedResultsController!=nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Entity"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *firstSort = [[NSSortDescriptor alloc] initWithKey:#"startDate"
ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:firstSort,nil];
[fetchRequest setSortDescriptors:sortDescriptors];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:#"sectionIdentifier"
cacheName:nil];
self.fetchedResultsController.delegate = self;
return self.fetchedResultsController;
}
Question 1: How do I get the sections to appear in the following order:
Section 0: Today
Section 1: Upcoming
Section 2: Past
Question 2: Within each section, how do I sort the rows based on an attribute called "modified" in each object?
Both section and row ordering is 100% dependent upon the sort descriptors. You want your first sort descriptor to sort everything into the proper section and then your following sort descriptors will sort the rows within the sections.
For example, if you wanted three sections based off of "group" and then you wanted the rows sorted by name inside of the group you would add the sort descriptors as:
NSArray *descriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"group" ascending:YES], [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES]];
[fetchRequest setSortDescriptors:descriptors];
Your section key for your NSFetchedResultsController will also need to match your first NSSortDescriptor.

NSFetchRequest Returns Fault from Core Data iOS

I am trying to fetch the stateName in below code and show it in a label. but it always returns fault.
-(NSArray *) getStateNameFromCode :(NSString *) stateCode
{
NSManagedObjectContext *objectContext = [self managedObjectContext ];
NSEntityDescription *entity = [NSEntityDescription entityForName:ENTITY_STATES inManagedObjectContext:objectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K == %#", COLUMN_STATE_CODE, stateCode];
NSLog(#"Predicate : %#" ,predicate);
NSFetchRequest *fetchRequest = [[ NSFetchRequest alloc]init];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
NSArray *stateName = [objectContext executeFetchRequest:fetchRequest error:Nil];
if (stateName.count > 0)
{
return [stateName objectAtIndex:0];
}
return nil ;
}
self.labelTeams.text = [NSString stringWithFormat:#"%#\n" ,
[sharedController getStateNameFromCode:_checklist.stateHomeTeam]]
;
OUTPUT:
<States: 0xa571560> (entity: States; id: 0xa565300 <x-coredata://D6B54D51-4556-41E1-A372-F39EB871A076/States/p8> ; data: <fault>)
Tried using setreturnsobjectsasfaults=NO but thats not working. found so many links most of them say to use setreturnsobjectsasfaults . I killing my brian.
Any ideas will be appreciated.
Regards,
Try this,
//return state name as NSString (assumes state name is string type)
-(NSString *) getStateNameFromCode :(NSString *) stateCode
{
....
NSArray *states = [objectContext executeFetchRequest:fetchRequest error:Nil];
if (states.count > 0)
{
//Matched state object
NSManagedObject *state = [states objectAtIndex:0];
//or States *state = [states objectAtIndex:0];, if States is the NSManagedObject subclass name
return //return name of state from state object, like state.name
}
return nil ;
}
self.labelTeams.text = [NSString stringWithFormat:#"%#\n" ,
[sharedController getStateNameFromCode:_checklist.stateHomeTeam]]
;

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.

fetching particular predicate from database

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.

Resources