My application generates multiple local notifications and while I'm testing it, I see that the app continuously receives the local notification appDelegate message. This is in spite of my having no repeat interval.
<UIConcreteLocalNotification: 0x1574b0>{fire date = (null), time zone = (null), repeat interval = 0, next fire date = 2011-09-23 19:40:35 +0000}
This is the debug value returned at my breakpoint. As you'll notice, there is no data except the next fire date, which shouldn't technically be called because there is no interval. Also, this is the only notification in the SharedApplication LocalNotifications array.
Related
I have a time notification in my swift app that sends a push notification locally everyday at 8. I want to add a button so that if it is pressed, it cancels the push notifications for that day only. My question is does removeAllPendingNotificationRequests() do the work or will it cancels time notifications forever?
It cancels all the pending notifications that you've registered. In your scenario you could store the idenfifiers of the Notification that you're registering in a dictionary where the key corresponds to each day which is of type Date and the value is an array of identifiers which is of type [String]. And if you want to cancel all the Notification for a particular Date you can get the array of String identifiers for that date from the above dictionary and cancel them like the following, here's an example:
let notificationsDictionary = [Data: [String]]()
guard let notificationsForToday = notificationDictionary[Data()] else { return }
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: notificationsForToday)
This question could be rephrased as: How to invoke a function if 2 seconds pass without an event (re)occurring?
I'm playing with SFSpeechRecogniser. While the user is speaking it sends continuous updates (maybe 2-3 per second). I'm trying to detect when the user stops speaking. If I don't receive any updates for (say) 2 seconds, I can assume that the user has paused speaking.
How to implement this in Swift?
I am aware that I could do:
var timer : Timer?
func f() {
on_event = { result, error in
print( "Got event, restarting timer" )
self.timer?.invalidate()
self.timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { _ in
print( "2s inactivity detected" )
self.timer?.invalidate()
NotificationCenter.default.post( name: inactivity_notification, object: nil )
}
}
}
But is it possible to do it without repeatedly creating and destroying the Timer instance (and thus creating a boatload of temporary Timer instances that never get used)?
One way to do it is to:
Record the current time when an event occurs
Set up a recurring timer with a granularity you are comfortable with (for example 0.25 seconds).
When the timer pops, check difference between current time and last event time. If that is greater than 2 seconds, fire your notification.
This is what I'd do if I had to recognize that a person had stopped typing for 2 seconds. Invalidating and creating timers at typing speed would be a lot of churn. You can tune this to your requirements depending on how close to exactly 2 seconds you need to be.
You could also do this by just having a timeSinceLastEvent variable, and set it to 0 when an event occurs. The recurring timer would increment this by the granularity, and check if it has reached 2 seconds and fire the notification if it had. This is cruder than doing the time math since the timer interval isn't guaranteed, but simpler.
Timer's .fireDate property is writable.
So every time a speech event occurs just do timer.fireDate = Date(timeIntervalSinceNow: 2)
I have a variable that keeps track of user statistic I want to reset at the beginning of each day. How can I do that?
Since the application is not allowed to run in the background, it seems I will have to do the check every time the application is active but I don't know how to reset the variable I have only once. This is the function I wanted to use:
let beginingOfDay = NSCalendar.currentCalendar().startOfDayForDate(NSDate())
func resetCurrentTime(){
// Date comparision to compare current date and begining of the day.
let dateComparisionResult:NSComparisonResult = NSDate().compare(beginingOfDay)
if dateComparisionResult == NSComparisonResult.OrderedDescending || dateComparisionResult == NSComparisonResult.OrderedSame {
// Current date is greater or equal to end date.
currentTime = 0 //reset the time tracker
}
}
I wanted to use this function to check when the application is launched but the problem is that the application could be launched many time a day. How I can reset my variable only once at the beginning of a day if the user is using the application or when the application becomes active or is launched for the first time that day?
Thanks
You can store in the user defaults this value.
So the flow is the following:
When the app is launched or became active you check whether the value of the variable in the user defaults is the same as the current day (e.g. 25/07/2016), then do nothing.
If the value is different, then you update the value in the user defaults with the current day.
If the app is running and the date is changed, you can update the value of your variable by subscribing to this notification:
UIApplicationSignificantTimeChangeNotification
I'm trying to get my app to call a function at specific time intervals. For example, I might want the function to be called every hour on the hour, so at 1:00 AM, 2:00 AM, and so on. I have tried doing this with an NSTimer, but I find that it has trouble staying in sync when resuming after the machine sleeps or is powered off. Is there a way for my app to detect when we have reached a specific date and time and to call a function at that time? Thanks.
You could try Grand Central Dispatch. Specifically use dispatch_walltime() to create a dispatch_time_t representing the time you want the job to run and then use dispatch_after() to submit the job to Grand Central Dispatch for execution at the specified time.
Run it every minute and test whether ≥ 1h has elapsed since the last invocation.
You could use a helper method similar to below in combination with the NSTimer. The timer could fire its selector function every sec/minute/etc in which you pass this helper a pair of currentDate/endDate and when the returned value is <= 0 then execute your timed event function once with a flag and move your endDate forward an hour.
func timeBetween(currentDate: NSDate, endDate: NSDate) -> Double
{
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Second], fromDate: currentDate, toDate: endDate, options: [])
return Double(components.second)
}
Is there anyway to show the notification with swift every 15 seconds ? I checked that via
notification.fireDate=NSDate(timeIntervalSinceNow: 15)
but it doesn't work everytime it just showed once , how we can do it as a loop ?
You can't schedule a notification every 15 second. The minimum time between notifications it is 1 minute which it is also very unlikely needed.
var repeatInterval: NSCalendarUnit { get set }
Description The calendar interval at which to reschedule the
notification. If you assign a calendar unit such as weekly
(NSWeekCalendarUnit) or yearly (NSYearCalendarUnit), the system
reschedules the notification for delivery at the specified interval.
Note that intervals of less than one minute are not supported. The
default value is 0, which means that the system fires the notification
once and then discards it.
So just set it up as follow:
notification.repeatInterval = .Minute
You can set localNotification.repeatInterval property which as to be of type NSCalendarUnit