Beginner trying to create an app that gives the user a random "word of the day".
Through testing I realised that the app has to be opened every day by the user in order to manually trigger the function isRefreshRequired()
(which retrieves the new word and updates user interface and notification content). But I need this to be done automatically, regardless of whether the user opens the app or not.
Is this even possible? I am stuck between which methods to use:
NSCalendarDayChanged. I found this useful answer but I am not sure where it would be implemented? If I use it applicationDidFinishLaunching, where would the function calendarDayDidChange() be called? In viewDidLoad()?
significantTimeChangeNotification() - Possibly a better method? Again, not sure how to actually implement this and where. The document also says:
If the the device is asleep when the day changes, this notification will be posted on wakeup.
Does wakeup mean when the app is reopened? Because I want the isRefreshRequired() function to execute even if the user hasn't touched the app.
- Background App Refresh: this doesn't seem useful since it needs a URLSession and the user may have disabled background refresh. Seems a bit excessive for an app that just wants to give the user a new word!
The code in question:
override func viewDidLoad() {
super.viewDidLoad()
isRefreshRequired()
}
func isRefreshRequired() {
// if it is first time opening app
if userDefaults.bool(forKey: "First Launch") == false {
//run code during first launch
_ = updateWordOfTheDay()
NotificationManager.askNotificationPermission()
print("First time opening app")
userDefaults.set(true, forKey: "First Launch")
}
else {
//run code after first launch
print("Not first time opening app")
userDefaults.set(true, forKey: "First Launch")
let lastAccessDate = userDefaults.object(forKey: "lastAccessDate") as? Date ?? Date()
userDefaults.set(Date(), forKey: "lastAccessDate")
// if it is the same day give the vocab picked for that day
if calendar.isDateInToday(lastAccessDate) {
readFromUserDefaults()
print("No refresh required as it is the same day as lastAccessDate which was \(lastAccessDate)")
}
else {
print("new day since lastAccessDate")
_ = updateWordOfTheDay()
}
}
}
func sendNotification(using: ChineseVocab) {
let center = UNUserNotificationCenter.current()
center.removeAllDeliveredNotifications()
center.removeAllPendingNotificationRequests()
let content = UNMutableNotificationContent()
content.title = using.Chinese + " " + using.Pinyin
content.body = using.Definition
}
func saveToUserDefaults(with data: ChineseVocab) {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(data) {
userDefaults.set(encoded, forKey: "selectedVocab")
}
}
func readFromUserDefaults() {
if let savedVocab = userDefaults.object(forKey: "selectedVocab") as? Data {
let decoder = JSONDecoder()
if let wordOfTheDay = try? decoder.decode(ChineseVocab.self, from: savedVocab) {
updateLabels(using: wordOfTheDay)
NotificationManager.sendNotification(using: wordOfTheDay)
print("readFromUserDefaults() is working: \(wordOfTheDay)")
} else {
print("unable to load readFromUserDefaults()")
}
}
}