8

Well, the title pretty much says it all. What I am trying to do is check when a date has passed. So, for example let us say that a user is using my app and then they go to bed and check my app in the morning. When my app opens up I need to check if the day has changed at all.

Also I don't really need to know this information when the app is terminated or in the background or anything. I just need to know if the date has changed when the app is running and the user is actually interacting with it.

Note: I have looked at other Stack Overflow Posts pertaining to this issue but none of them have helped me.

Harish
  • 1,374
  • 17
  • 39

3 Answers3

16

Implement to observe

NSCalendarDayChangedNotification

Posted whenever the calendar day of the system changes, as determined by the system calendar, locale, and time zone. This notification does not provide an object.

If the the device is asleep when the day changes, this notification will be posted on wakeup. Only one notification will be posted on wakeup if the device has been asleep for multiple days.

There are no guarantees about the timeliness of when this notification will be received by observers. As such, you should not rely on this notification being posted or received at any precise time.

The notification is posted through [NSNotificationCenter defaultCenter].

Example:

In applicationDidFinishLaunching add

NSNotificationCenter.defaultCenter().addObserver(self, selector:"calendarDayDidChange:", name:NSCalendarDayChangedNotification, object:nil)

and implement the method

func calendarDayDidChange(notification : NSNotification)
{
   doSomethingWhenDayHasChanged()
}

or use the block API.

If the class including the observer is not the application delegate class you might remove the observer at some time.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • Also, I tried this code `let noteCenter = NSNotificationCenter.defaultCenter() let observer = noteCenter.addObserverForName(NSCalendarDayChangedNotification, object: nil, queue: NSOperationQueue.currentQueue(), usingBlock: { notificationCenter in })`. How do I execute the query though? – Harish Feb 20 '16 at 16:55
  • This only works if your app is running at midnight when the date changes. If the device is locked and/or your app is suspended, this won't work. Matt's approach, in the answer that got deleted, is a better fit for the OPs question. Save the NSDate to user defaults on a suspend event, and then next time you get launched or return to the foreground, read the saved date, use NSCalendar to see if the date has changed, and there you go. – Duncan C Feb 20 '16 at 16:58
  • @DuncanC Oh ok, I thought this would work even if the app was suspended. But, once the user opens up the device won't I still get the Notification like the answer mentions? – Harish Feb 20 '16 at 17:00
7

Update vadian's reply to Swift 5:

NotificationCenter.default.addObserver(self, selector:#selector(self.calendarDayDidChange(_:)), name:NSNotification.Name.NSCalendarDayChanged, object:nil)

and implement the method

@objc private func calendarDayDidChange(_ notification : NSNotification) {
    doSomethingWhenDayHasChanged()
}
villb
  • 195
  • 3
  • 8
0

If you update the UI, to prevent crashes use this code:

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector:#selector(self.calendarDayDidChange(_:)), name:NSNotification.Name.NSCalendarDayChanged, object:nil)
}

@objc private func calendarDayDidChange(_ notification : NSNotification) {
    DispatchQueue.main.async { [weak self] in
        self?.setupLabel()
    }
}
Display Name
  • 4,502
  • 2
  • 47
  • 63