I'm trying to figure out how I can make an alert popup once the user has reached their goal. However, I only want it to show once a day after it's been triggered. Apologies in advance. if my logic is off with tackling this issue.
// Check to see if hydration goal has been reached
if (waterCups >= dailyHydrationGoal) {
// User has reached goal
if (alert has not been fired yet today) {
// alert pop up you reached your goal!
}
}
How would I go about ensuring it only launches once per day?
You can use isDateInToday: method to check whether the given date is in “today.”
NSDate *lastAlertDate = (NSDate *)[[NSUserDefaults standardUserDefaults] objectForKey:#"lastAlertDate"];
if(![[NSCalendar currentCalendar] isDateInToday:lastAlertDate]){
//Show alert
NSDate *today= [NSDate date];
[[NSUserDefaults standardUserDefaults] setObject:today forKey:#"lastAlertDate"];
}
Do you have a persistence store? (NSUserDefaults, core data etc...)
You can store a time stamp (NSDate) of the last time an alert was shown then check if the last time it was shown is today. How to determine if an NSDate is today?
If an alert has not been shown today, pop an alert and record a new time stamp.
Related
I have 2 UIDatePickers, one set in UIDatePickerModeDate and the other in UIDatePickerModeTime.
If the first one has its date set to today, then the second one must have a restriction such that the user cannot select a time that is before now. To do this I use the setMinimumDate function. However, if the user sets a date in the future, I need to reset the minimumDate property, meaning that there should be no minimumDate set on the picker.
I am able to achieve this by calling
[self.timePicker setMinimumDate:nil];
But this gives me an exception in the Xcode console output as below.
-[__NSCFCalendar components:fromDate:]: date cannot be nil
Future exception.
A few of these errors are going to be reported with this complaint, then further violations will simply be ignored.
How can I remove the minimumDate property of my timePicker after it has been set, without this exception being raised?
Thank you.
EDIT:
The reason I tried setting it to nil was because Apple's documentation says that the default value of the minimumDate property is nil (here).
Also, I did try to set the minimum date to the future date selected by the user, after making the time component zero. This causes the time to be selected as 12 AM in the picker which is acceptable. Now if the user selects today's date again, nothing happens when I set the minimumDate property, i.e. I cannot toggle the minimumDate using this. The code is as follows:
(void)setMinimumDateForTimePicker {
if([[NSCalendar currentCalendar] isDateInToday:self.datePicker.date]) {
NSLog(#"Min date for today");
[self.timePicker setMinimumDate:[self roundUpToNearestFifteenMinutes:[NSDate date]]];
} else {
// date is in the future so zero out time
NSLog(#"Min date for the future");
NSDateComponents* selectedDateWithZeroTime = [[NSCalendar currentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self.datePicker.date];
[self.timePicker setMinimumDate:[[NSCalendar currentCalendar] dateFromComponents:selectedDateWithZeroTime]];
}
[self updateStartTimeField:nil];
}
This is the code that worked finally for what I was trying to do.
- (void)setMinimumDateForTimePicker {
if([[NSCalendar currentCalendar] isDateInToday:self.datePicker.date]) {
[self.timePicker setMinimumDate:[self roundUpToNearestFifteenMinutes:[NSDate date]]];
} else {
[self.timePicker setMinimumDate:[[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]]];
}
[self updateStartTimeField:nil];
}
I have being wondering these days how can I subtract 3, 10 and 20 minutes from selected time from time picker in Swift 3. So for example when the user selects the start time of an event, to be able to receive notification 3, 10 or 20 minutes before the selected from the picker time value. I have tried
let value:TimeInterval = 1187.5
let periodComponents = startTimePicker.date.addingTimeInterval(-value)
for the 20 minutes earlier,
but I'm getting the value 2 hours behind(may be the console is showing me the GTM time only). Is it possible to schedule notification from "periodComponens" to repeat every week on the selected time on specific day of the week? Or I should use other subtracting method?
Use the built-in Calendar class:
let threeMinutesEarlier = Calendar.current.date(byAdding: .minute, value: -3, to: myPicker.date)
There is nothing wrong with your code.
The xcode console just prints out GMT date time by default. If you use NSDateFormatter to convert your NSDate into NSString and print it out, the result will be as you expected
If you use UILocalNotification and wish to schedule it to fire weekly you can set its provided property repeatInterval to NSCalendarUnitWeekOfYear.
For example:
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
NSDate *fireTime; // Your desired date time.
localNotif.fireDate = fireTime;
localNotif.repeatInterval = NSCalendarUnitWeekOfYear;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
Is it possible to have an action from a button a) do an NSDate store when tapped, and then b) for that method to do a date comparison with an if statement?
So, for instance, if the stored NSDate was less than 12 hours ago, the user could not press the button again?
Haven't come across a tip on this from my research.
Sure. You can get current date by code
[NSDate date]
Then save him into NSUserDefaults
And check a current date with saved date on button press.
How
if ( [[NSDate date] timeIntervalSinceDate: savedDate] >= 12*60*60) // 12 hours
{
// do your steps
}
I'm working on app that sets an UILocalNotification. This is the first time I use it and I'd like to have some explanations to use it efficiently and in the best way.
Which is the bast way to countdown to the time of notification expiration? I'd like to show to the user an UILabel with the missing time, this UILabel updates every second and when I reopen my app it must show the timer.
I've done this in this way:
When I reopen my app or the recall the view that has to show the timer I check if there is a UILocalNotification with the userInfo I've setted previously then I subtract to its NSDate
the current time so I get the difference, and update the UILabel. I know it shows time in seconds but if this procedure it's good I will convert it into time.
Is there any best way to do this?
Here is my code:
UILocalNotification *countDownNotificationSetted;
NSArray *scheduledNotificationArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
for (int i = 0; i<[scheduledNotificationArray count]; i++)
if ([[[[scheduledNotificationArray objectAtIndex:i] userInfo] objectForKey:#"ID"] isEqualToString:#"ParkNotification"]) {
countDownNotificationSetted = [scheduledNotificationArray objectAtIndex:i];
break;
}
NSDate *expringDate = [countDownNotificationSetted fireDate];
NSTimeInterval timeLeftToNotification = [expringDate timeIntervalSinceNow];
if(timeLeftToNotification == 0){
[countDownTimer invalidate];
}
datePicker.countDownDuration = timeLeftToNotification;
_countDownLabel.text = [NSString stringWithFormat:#"%.0f", timeLeftToNotification];
NSLog(#"%.0f", timeLeftToNotification);
I think it would be better if you would update your label with a timer as you already do , when you close the app, store that time locally in a file or user defaults and when the app launches again read from that file the time. Or if you want the time passed since the first openning of the app, just write the time in appDidFinishLaunching and get it from there every time . I don't see the benefit of the local notification here.
Hope this helps.
Cheers!
I have the following code below that is meant to change a class var called "today" forward or backward by one day. It will work one time but then after that it crashes. It will do the same no matter if I press the left button or right button. What am I doing wrong?
the var today is a class var initiated as .. today = [NSDate date]
Here is the method that crashes:
(IBAction)changeDateByOne:(id)sender{
NSDate *newDay;
NSDate *currentDay = today;
NSTimeInterval secondsPerDay = 24 * 60 * 60;
if(sender == leftButton){
newDay = [currentDay addTimeInterval:-secondsPerDay];
}else if(sender == rightButton) {
newDay = [currentDay addTimeInterval: secondsPerDay];
}
today = newDay;
}
Not only do you need to retain the date created, but you also need to release the existing value held by "today," otherwise you'll leak the old reference.
When initializing the instance, use:
today = [[NSDate date] retain];
I would change the last line to:
[today release];
today = [newDay retain];
And finally, in your dealloc method, add:
[today release];
before calling [super dealloc];
You need to read the memory management documentation. That’s here:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
If you’re adding or subtracting days, you might want to read this which is an alternative way of doing the same thing:
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtCalendricalCalculations.html#//apple_ref/doc/uid/TP40007836-SW1
Lastly, if something crashes, it’s often helpful to look at the back traces (and include them in your questions if you can’t figure it out for yourself). Memory management bugs are usually the problem if you see objc_msgSend (or one of its companions) in the trace.
Maybe you need to say
today = [[NSDate date] retain]
I think you need to retain the newDay object returned from the addTimeInterval method. You may also need to release today before you do the assignment at the end.