Parse this month only - objective-c

I am new to parse and I need help retrieve objects that are in the current month.
First I have a class called food and have a column of type Date called food_date
I am assuming I have to use greaterThan and less Than, but I am unsure how to.
NSDate *thisMonth = [NSDate date];
PFQuery *foodList = [PFQuery queryWithClassName:#"food"];
[foodList whereKey:#"food_date"

I think you need something like this :
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
components.day = 1;
// Get the date of the first day of the current month
NSDate *minimumDate = [calendar dateFromComponents:components];
components.month = components.month + 1;
// Get the date of the first day of the next month
NSDate *maximumDate = [calendar dateFromComponents:components];
PFQuery *foodList = [PFQuery queryWithClassName:#"food"];
[foodList whereKey:#"food_date" greaterThanOrEqualTo:minimumDate];
[foodList whereKey:#"food_date" lessThan:maximumDate];
[foodList findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// The find succeeded.
NSLog(#"Successfully retrieved %d foods.", objects.count);
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
I hope that help.

Related

HealthKit Read data Heart Rate and BloodPressure 'latest update after sync'

I am syncing Heart Rate and BloodPressure data from HealthKit.
The problem with this approach is when the user enters historic data which will not be synced. How do I perform the same query but with CreationDate (instead of StartDate), or some kind of database ID which will identify the historic value as being newer?
I just want to filter out all the newly created values from healthkit.
-(void)getSpecificHealthKitDataHeartReat:(NSDate*)myDate
{
NSDateFormatter *dtFormat = [[NSDateFormatter alloc] init];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:now];
NSDate *startDate = [calendar dateFromComponents:components];
NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];
NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];
//[HKQuery predicateForObjectWithUUID:(nonnull NSUUID *)]
//Read HeartRate
HKHealthStore *healthStore = [[HKHealthStore alloc] init];
NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierStartDate ascending:YES];
HKQuantityType *heartRateType2 = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
HKSampleQuery *sampleQuery2 = [[HKSampleQuery alloc] initWithSampleType:heartRateType2 predicate:predicate limit:0 sortDescriptors:#[timeSortDescriptor] resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error)
{
if (!results)
{
NSLog(#"There are no heart rate results. The error was: %#.", error);
return;
}
else
{
NSMutableArray *hrArray = [[NSMutableArray alloc]init];
for(HKQuantitySample *samples in results)
{
HKQuantity *hrQuantity = [samples quantity];
// double hr = [hrQuantity doubleValueForUnit:[HKUnit unitFromString:#"count/min"]];
double hr = [hrQuantity doubleValueForUnit: [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]]];
NSLog(#"hr %f",hr);
NSLog(#"startDate %#",samples.startDate);
NSLog(#"endDate %#",samples.endDate);
}
}
}];
// Execute the query
[healthStore executeQuery:sampleQuery2];
}
Use HKAnchoredObjectQuery (documentation here). It is designed for exactly this use case.

Set Alarm on multiple days using local notification in ios 10 +Objective c

I use UNUserNotificationCenter for local notification. I want to fire a local notification on multiple days from present date and if user select repeat then every week on same day and same time notification fire which days are selected by user. So i use the below code.
NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitWeekOfYear|NSCalendarUnitWeekday fromDate:now];//get the required calendar units
if (components.weekday>4)
{
components.weekOfYear+=1;//if already passed monday, make it next monday
}
components.weekday = 4;//Wednesday
components.hour = 12;
NSDate *fireDate = [calendar dateFromComponents:components];
UNUserNotificationCenter *centerMonday;
UNMutableNotificationContent *objNotificationContent = [[UNMutableNotificationContent alloc] init];
objNotificationContent.title = #"change time";
objNotificationContent.body = #"This is local notification message! Every Wednesday";
objNotificationContent.sound = [UNNotificationSound defaultSound];
/// 4. update application icon badge number
objNotificationContent.badge = #([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1);
NSDateComponents *triggerDate = [[NSCalendar currentCalendar] components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:fireDate];
UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:triggerDate repeats:YES];
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:#"swami12"
content:objNotificationContent trigger:trigger];
/// 3. schedule localNotification
centerMonday = [UNUserNotificationCenter currentNotificationCenter];
centerMonday.delegate= self;
[centerMonday addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error)
{
if (!error)
{
NSLog(#"Local Notification succeeded");
}
else
{
NSLog(#"Local Notification failed");
}
}];
So here i set repeat yes but notification comes only once on selected day not repeat every week. Help, I stuck here from last three days.Thanks

How do I Isolate an Event's Title/Time in a variable to display on Storyboard?

Here's the full description of my problem: I am fetching the events of a calendar for a full day (i.e.today) and storing them in an array. How do I isolate the next relevant (one that has not passed) event's title and time from the array to display them separately as labels?
Here's my code:
//Load Calendar Events
EKEventStore *store = [[EKEventStore alloc] init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted,
NSError *error) {
if (granted) {
NSLog(#"User has granted permission");
// Get the appropriate calendar
NSCalendar *calendar = [NSCalendar currentCalendar];
// Create the start date components
NSDateComponents *beginDayComponents = [[NSDateComponents alloc] init];
beginDayComponents.day = 0;
NSDate *todayStart = [calendar dateByAddingComponents:beginDayComponents
toDate:[NSDate date]
options:0];
// Create the end date components
NSDateComponents *endDayComponents = [[NSDateComponents alloc] init];
endDayComponents.day = 0;
NSDate *todayEnd = [calendar dateByAddingComponents:endDayComponents
toDate:[NSDate date]
options:0];
// Create the predicate from the event store's instance method
NSPredicate *predicate = [store predicateForEventsWithStartDate:todayStart
endDate:todayEnd
calendars:nil];
// Fetch all events that match the predicate
NSArray *events = [store eventsMatchingPredicate:predicate];
NSLog(#"Here are the events in the array, %#", events);
} else {
NSLog(#"User has not granted permission");
}
}];
Thanks in advance, and have a good day!
As apple states in its EKEventStore-documentation you will have to sort your array first, so that the next pending event is at index 0.
Note: Retrieving events from the Calendar database does not
necessarily return events in chronological order. To sort an array of
EKEvent objects by date, call sortedArrayUsingSelector: on the array,
providing the selector for the compareStartDateWithEvent: method.
I'd suggest you then just pick the EKEvent-Object at index 0 of your array and read the properties from it and set them on your label.
EKEvent *event = [events objectAtIndex:0];
yourTitleLabel.text = event.text;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateformat = #"dd.MM HH:mm";
yourDateLabel.text = [formatter stringFromDate:event.startDate];
Edit:
You would sort your array events like this:
events = [events sortedArrayUsingSelector:#selector(compareStartDateWithEvent:)];
For this to work, you have to import EventKit/EventKit.h

Using Core Data with NSPredicate and NSDate

I have a Event table that saves a NSString *action and a NSDate *date. I want to filter the array retrieved from core data to display all the actions performed in the last hour and the next hour not depending on the day it was saved. Example on Tuesday a action was saved on 16:00 but Today is Friday 17:00 and I still want to retrieve that action saved on Tuesday and any action within that time frame.
For anyone stuck with this problem. Changed my Event Table to hold a integer (hour of the action) and retrieved it like this
NSDate *currentFullDate = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:currentFullDate];
NSInteger currentHour = [components hour];
NSInteger hourAgo = currentHour -1;
NSInteger nextHour = currentHour +1;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Event"];
request.predicate = [NSPredicate predicateWithFormat:#"(hour >=%#) AND (hour <= %#)", hourAgo, nextHour];
request.fetchLimit = 5;
NSError *error;
NSArray *eventArray = [managedObjectContext executeFetchRequest:request error:&error];
for (Event *event in eventArray)
{
}

NSNumber from NSDate

I'm attempting to get around a date validation that refuses to take anything earlier than tomorrow.
So far I have this:
NSDate *dateY = [NSDate dateWithTimeIntervalSinceNow:-86400];
// Negative one day, in seconds (-60*60*24)
NSLog(#"%#", [NSDate date]);
// "yyyy-MM-dd HH:mm:ss Z", accurate assuming Z = +0000
NSLog(#"%#", dateY);
// "yyyy-MM-dd HH:mm:ss Z", same accuracy (minus one day)
That's great, but dateY is not an NSNumber. I need an NSNumber for the comparison, but I can't find anything that works. (I don't even know how an NSNumber can be 2011-04-14 13:22:29 +0000, anyway...)
I can use NSDateFormatter to convert an NSDate into an NSString, so if it would be possible to take that string and convert it to the required NSNumber (as opposed to directly converting the NSDate to an NSNumber, which I can't seem to find help with either), that would be fine.
- (BOOL)validateDueDate:(id *)ioValue error:(NSError **)outError {
NSDate *dateY = [NSDate dateWithTimeIntervalSinceNow:-86400];
NSNumber *tis1970 = [NSNumber numberWithDouble:[dateY timeIntervalSince1970]];
NSLog(#"NSNumber From Date : %#", tis1970);
NSLog(#"Date From NSNumber : %#", [NSDate dateWithTimeIntervalSince1970:[tis1970 doubleValue]]);
// Due dates in the past are not valid
// Enforced that a due date has to be >= today's date
if ([*ioValue compare:[NSDate date]] == NSOrderedAscending) {
if (outError != NULL) {
NSString *errorStr = [[[NSString alloc] initWithString:#"Due date must be today or later."] autorelease];
NSDictionary *userInfoDictionary = [NSDictionary dictionaryWithObject:errorStr forKey:#"ErrorString"];
NSError *error = [[[NSError alloc]
initWithDomain:TASKS_ERROR_DOMAIN
code:DUEDATE_VALIDATION_ERROR_CODE
userInfo:userInfoDictionary] autorelease];
*outError = error;
}
return NO;
} else {
return YES;
}
}
Right now, the user is not allowed to choose a date before tomorrow. errorStr lies. Before today makes more sense than before tomorrow as a rule for refusing to save the date, so I've been fighting with this thing to let me use yesterday in place of today, rather than looking any deeper.
Edit: Using NSOrderedSame allows any date to be selected without an error. That won't do.
You can convert an NSDate to an NSNumber like this:
NSDate *aDate = [NSDate date];
NSNumber *secondsSinceRefDate = [NSNumber numberWithDouble:[aDate timeIntervalSinceReferenceDate]];
and convert back like:
aDate = [NSDate dateWithTimeIntervalSinceReferenceDate:[NSNumber doubleValue]];
All that is needed to get a NSNumber is
NSDate *dateY = [NSDate dateWithTimeIntervalSinceNow:-86400];
NSNumber *tis1970 = [NSNumber numberWithDouble:[dateY timeIntervalSince1970]];
NSLog(#"NSNumber From Date : %#", tis1970);
NSLog(#"Date From NSNumber : %#", [NSDate dateWithTimeIntervalSince1970:[tis1970 doubleValue]]);
You should never use 86400 to calculate date differences, because not all days have 86,400 seconds in them. Use NSDateComponents instead:
- (BOOL)validateDueDate:(NSDate *)dueDate error:(NSError *)error {
NSDate *today = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:today];
//adjust the components to tomorrow at the first instant of the day
[components setDay:[components day] + 1];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
NSDate *tomorrow = [calendar dateFromComponents:components];
NSDate *earlierDate = [dueDate earlierDate:tomorrow];
if ([earlierDate isEqualToDate:dueDate]) {
//the dueDate is before tomorrow
if (error != nil) {
NSString *errorStr = [[[NSString alloc] initWithString:#"Due date must be today or later."] autorelease];
NSDictionary *userInfoDictionary = [NSDictionary dictionaryWithObject:errorStr forKey:NSLocalizedDescriptionKey];
*error = [[[NSError alloc] initWithDomain:TASKS_ERROR_DOMAIN code:DUEDATE_VALIDATION_ERROR_CODE userInfo:userInfoDictionary] autorelease];
}
return NO;
}
return YES;
}
WARNING: code typed in a browser. Caveat Implementor