I’m developing a game that offers free gems every day. The app checks if the gems have been claimed, and if they haven’t, it displays a badge with a count of 1. Once the gems are claimed, the current date is stored in an array lastClaimDate to prevent the player from claiming gems again on the same day.
I want to send a notification if the gems have not been claimed yet. I attempted to do this using the sendNotification() function, which should display a notification banner at the top of the screen. However, I couldn’t get this to work, so I switched to trying a simpler approach: sending a notification at midnight using sendMidnightNotification(). The idea is that every morning, the user would see a notification that gems can be claimed.
While the badge updates correctly, the notification banner or alert does not appear at all.
Longterm I want the app to check in the background if the gems have not been claimed and send a message at 9 PM. (Meaning if the player logged in in the morning and claimed the gems there is no notification, but on the next day if the player did not log in and claim the gems they will get a notification pop up).
Here’s the relevant code:
import SwiftUI
import BackgroundTasks
import UserNotifications
class AppDelegate: UIResponder, UIApplicationDelegate {
@AppStorage("lastClaimDate") private var lastClaimDate: [String] = [""]
private var currentDateString: String {
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
return dateFormatter.string(from: currentDate)
}
func canGemsBeClaimed() -> Bool {
return !lastClaimDate.contains(currentDateString)
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "ijouClaimGemsNotification", using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
sendMidnightNotification()
// Request notification permission
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if let error = error {
print("Notification permission error: (error)")
}
}
return true
}
func applicationDidEnterBackground(_ application: UIApplication) {
scheduleAppRefresh()
}
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "ijouClaimGemsNotification")
request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 60) // 60 seconds
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("Could not schedule app refresh: (error)")
}
}
func handleAppRefresh(task: BGAppRefreshTask) {
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
scheduleAppRefresh()
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 5
let operation = BlockOperation {
if self.canGemsBeClaimed() {
self.sendNotification()
self.setBadgeCount(1)
} else {
self.setBadgeCount(0)
}
}
task.expirationHandler = {
queue.cancelAllOperations()
}
operation.completionBlock = {
task.setTaskCompleted(success: !operation.isCancelled)
}
queue.addOperation(operation)
}
func sendMidnightNotification() {
// Create the notification content
let content = UNMutableNotificationContent()
content.title = "New Gems Available"
content.body = "New gems can be claimed."
content.sound = .default
content.badge = 1
// Set up the trigger to fire at midnight
var dateComponents = DateComponents()
dateComponents.hour = 0 // Midnight (00:00)
dateComponents.minute = 0
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
// Create the request
let request = UNNotificationRequest(identifier: "MidnightGemsNotification", content: content, trigger: trigger)
// Schedule the notification
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
print("Error scheduling notification: (error)")
}
}
}
func sendNotification() {
let content = UNMutableNotificationContent()
content.title = "Gems Available"
content.body = "You can now claim new gems!"
content.sound = .default
content.badge = 1
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
let request = UNNotificationRequest(identifier: "GemsNotification", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
func setBadgeCount(_ count: Int) {
UNUserNotificationCenter.current().setBadgeCount(count, withCompletionHandler: { error in
if let error = error {
print("Failed to set badge count: (error)")
}
})
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound, .badge])
}
}
Any help on why the notification is not displaying would be greatly appreciated.