I’m new to iOS improvement and presently engaged on a function to schedule day by day native notifications in my app. Right here’s the way it’s imagined to work:
• Notifications show textual content from a JSON file.
• Customers can regulate the time for the notification utilizing a DatePicker within the app settings, however there’s a default time set initially.
• Notification is scheduled for default time after the consumer grants permission for notifications.
All the pieces works as anticipated apart from the very first notification after putting in the app. It doesn’t set off on the default set time. Notifications solely begin working after the consumer manually adjustments the time utilizing the DatePicker in my app settings.
I’m unsure why this occurs. I’ve verified that permissions are granted and that scheduling logic runs when the app begins. Is there one thing I could be lacking relating to default values or the notification scheduling?
Any hints or ideas could be vastly appreciated. Thanks prematurely!
My code:
import Basis
import UserNotifications
class DailyQuoteNotificationManager {
static let shared = DailyQuoteNotificationManager()
non-public init() {}
func scheduleDailyQuote() {
let userDefaults = UserDefaults.normal
// überprüft den aktuellen Berechtigungsstatus füt Benachrichtigungen
UNUserNotificationCenter.present().getNotificationSettings { settings in
DispatchQueue.primary.async {
swap settings.authorizationStatus {
case .licensed:
self.scheduleNotification()
userDefaults.set(Date(), forKey: "lastScheduledDate")
case .notDetermined:
self.requestNotificationPermission { granted in
if granted {
self.scheduleNotification()
userDefaults.set(Date(), forKey: "lastScheduledDate")
} else {
print("Notification permission not granted after request.")
}
}
default:
print("Notification permission not granted or denied.")
}
}
}
}
non-public func loadQuotes(from fileName: String) -> [QuranQuoteNotification]? {
guard let url = Bundle.primary.url(forResource: fileName, withExtension: "json") else {
return nil
}
do {
let knowledge = strive Information(contentsOf: url)
let decoder = JSONDecoder()
let jsonDict = strive decoder.decode([String: [QuranQuoteNotification]].self, from: knowledge)
return jsonDict["quranQuotes"]
} catch {
print("Error decoding file: (fileName).json: (error)")
return nil
}
}
func getNotificationTime() -> Date {
let userDefaults = UserDefaults.normal
return userDefaults.object(forKey: "dailyQuoteNotificationTime") as? Date ?? defaultTime()
}
func setNotificationTime(_ date: Date) {
let userDefaults = UserDefaults.normal
userDefaults.set(date, forKey: "dailyQuoteNotificationTime")
}
non-public func defaultTime() -> Date {
var parts = DateComponents()
parts.second = 00
parts.minute = 00
parts.hour = 09
parts.timeZone = TimeZone.present
return Calendar.present.date(from: parts) ?? Date()
}
non-public func requestNotificationPermission(completion: @escaping (Bool) -> Void) {
let middle = UNUserNotificationCenter.present()
middle.requestAuthorization(choices: [.alert, .sound, .badge]) { granted, error in
DispatchQueue.primary.async {
if let error = error {
print("Error requesting notification permission: (error.localizedDescription)")
}
completion(granted)
}
}
}
non-public func scheduleNotification() {
let languageCode = Locale.present.language.languageCode?.identifier ?? "en"
let jsonFileName = (languageCode == "de") ? "quotes_de" : "quotes_en"
guard let quotes = loadQuotes(from: jsonFileName),
let randomQuote = quotes.randomElement() else {
return
}
let content material = UNMutableNotificationContent()
content material.title = (languageCode == "de") ? "Vers des Tages" : "Verse of the Day"
content material.physique = randomQuote.quote
content material.sound = .default
let notificationTime = getNotificationTime()
let dateComponents = Calendar.present.dateComponents([.hour, .minute], from: notificationTime)
let set off = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: "dailyQuote", content material: content material, set off: set off)
let middle = UNUserNotificationCenter.present()
middle.removePendingNotificationRequests(withIdentifiers: ["dailyQuote"])
middle.add(request) { error in
if let error = error {
print("Error scheduling notification: (error.localizedDescription)")
} else {
print("Every day quote notification scheduled for (notificationTime.formatted()).")
}
}
}
}
My DatePicker:
@State non-public var dailyVerseNotificationTime = DailyQuoteNotificationManager.shared.getNotificationTime()
DatePicker("Verse of the Day at:", choice: $dailyVerseNotificationTime, displayedComponents: .hourAndMinute)
.datePickerStyle(.compact)
.font(.appFont(16))
.body(top: 46)
.padding(.horizontal)
.background(.white)
.cornerRadius(12)
.overlay(
RoundedRectangle(cornerRadius: 12)
.inset(by: 0.35)
.stroke(Shade(purple: 0.9, inexperienced: 0.9, blue: 0.9), lineWidth: 0.7)
)
.padding(.high, 10)
.onChange(of: dailyVerseNotificationTime) {
DailyQuoteNotificationManager.shared.setNotificationTime(dailyVerseNotificationTime)
DailyQuoteNotificationManager.shared.scheduleDailyQuote()
print(dailyVerseNotificationTime)
}
I attempted and examined by way of simulator and actual machine, however notifications solely go off after manually altering the time with the date picker.