How to detect day change in Swift
You need to add an observer for "UIApplicationSignificantTimeChangeNotification"
:
NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: UIApplicationSignificantTimeChangeNotification, object: nil)
For Swift 4.2 or later
NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: UIApplication.significantTimeChangeNotification, object: nil)
Note: If your intent is to be notified when the day changes you can use .NSCalendarDayChanged
("NSCalendarDayChangedNotification"
) instead of UIApplication.significantTimeChangeNotification
.
NotificationCenter.default.addObserver(self, selector: #selector(dayChanged), name: .NSCalendarDayChanged, object: nil)
And add the selector method to the view controller where you would like to monitor the day changes:
@objc func dayChanged(_ notification: Notification) {
}
Detecting Day Change in iOS App
Solution which saves an integer value (the day) in NSUserDefaults
In AppDelegate create a method
checkDayChange
which compares theday
component of the current date with a saved value inNSUserDefaults
(default is 0). If the values are not equal, callresetValues
and save the current day.- (void)checkDayChange
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSInteger currentDay = [[NSCalendar currentCalendar] component:NSCalendarUnitDay fromDate:[NSDate date]];
NSInteger savedDay = [defaults integerForKey:@"day"]; // default is 0
if (currentDay != savedDay) {
[self resetValues];
[defaults setInteger:currentDay forKey:@"day"];
}
}Observe
NSCalendarDayChangedNotification
with selectorcheckDayChange
- Call
checkDayChange
also inapplicationDidFinishLaunching
andapplicationDidBecomeActive
Swift 3: Find out, if the date has changed - how?
You need to use Calendar
method isDateInToday
to check date is today's date. Also you need to put the code before returning value from function.
if !Calendar.current.isDateInToday(oldDate) {
defaults.set(Date(), forKey: "oldDate")
return true
}
return false
Checking when a date has passed - Swift
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.
How to check the date everyday in swiftUI
You can use
- (void)applicationSignificantTimeChange:(UIApplication *)application;
in AppDelegate to monitor such changes.You can also register for a notification in AppDelegate
UIApplication.significantTimeChangeNotification
iOS will call both the registered notification method as well above delegate method.
NotificationCenter.default.addObserver(self, selector: #selector(timeChanged), name: UIApplication.significantTimeChangeNotification , object: nil)
@objc func timeChanged() {
print("App Time Changed")
}
- In case you want to hook up with your SwiftUI directly, you can register your Swift view with your publisher.
Publisher will listen for notification nameUIApplication.significantTimeChangeNotification
.
Either of the ways can be used based on your requirement.
struct ContentView: View {
@State var dayDetails: String = "Hello World"
var body: some View {
Text(dayDetails)
.padding().onReceive(NotificationCenter.default.publisher(for: UIApplication.significantTimeChangeNotification), perform: { _ in
dayDetails = "Day has changed"
})
}
}
what's an efficient way in swift to get a change of day event
you could try something like this:
(note I did not wait to see if this works)
import SwiftUI
import Combine
#if os(iOS)
import UIKit
#endif
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
Text("day change")
.onReceive(NotificationCenter.default.publisher(
for: UIApplication.significantTimeChangeNotification)) { _ in
print("----> day time has changed <----\n")
print("A notification that posts when there is a significant change in time, \n for example, change to a new day (midnight), \n carrier time update, and change to or from daylight savings time.")
}
}
}
Check if today is a new day SwiftUI
you could try something like this:
import SwiftUI
struct ContentView: View {
@State var lastDay: Date = Date()
@State var isToday = false
@State var selectedTime = 8 // 24 hour clock
var body: some View {
Text("your main view")
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in
// store the date whenever you go into background
print("---> storing: \(Date())")
UserDefaults.standard.set(Date(), forKey: "lastDay")
}
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
// try to retrieve the date when you come back from background
print("\n----> try retrieve lastDay")
if let temDate = UserDefaults.standard.object(forKey: "lastDay") {
self.lastDay = temDate as! Date
print("----> retrieved lastDay: \(self.lastDay)")
if Calendar.current.isDate(Date(), inSameDayAs: self.lastDay) {
self.isToday = true
print("----> isToday: \(self.isToday)\n")
// if it is 8 am or later do something
if let thisHour = Calendar.current.dateComponents([.hour], from: Date()).hour {
if (thisHour >= self.selectedTime) {
print("----> it is 8am or later --> do something")
// self.doSomething()
}
}
}
}
}
}
}
NotificationCenter is Apple internal message system. SwiftUI can listen for specific events, like when the App goes into the background. This is what this line does:
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification))
Now, this line:
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification))
listens for when you come back from the background, as mentioned in the comments.
There is no slowing down because of these onReceives.
What I have shown is an approach, you can add other .onReceive, such as:
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification)) { _ in
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willTerminateNotification)) { _ in
These can be used for when you start the App, and when you quit the App.
Related Topics
Problem with Swiftui and Foreach on Xcode Playground
Swiftui Navigationview Not See Image
Applescript Email Attachment Not Working in Handler
Invalid Update: Invalid Number of Rows in Section 1
Error Domain=Nscocoaerrordomain Code=3840 "Invalid Value Around Character 0
Mapview Shows White Overlay on Interaction
Implement an Equatable Void (None) Type
Passing Values Between Viewcontrollers Based on List Selection in Swift
Force Refresh on Another Viewcontroller Component with Swift
Why Swift Disallows Weak Reference for Non-Optional Type
Swiftui: Unable to Animate Images
My UIcollectionview Does Not Scroll Smoothly Using Swift
Why Does User Defaults Publisher Trigger Multiple Times
Secidentity + Force Cast Violation: Force Casts Should Be Avoided. (Force_Cast)
Wrong Image Orientation After Displaytransform Call
Custom Markers Disappear on Zoomin The Map and Appear on Zoomout The Map with Clustering