Natives iOS-App-Gerüst (Xcode 26, synchronisierte Ordner, iOS 18+). Features: - Gewohnheiten anlegen (Name, SF-Symbol, Farbe), heute abhaken, Streaks, Löschen - Detailansicht mit Monatskalender (Tage nachtragbar) und Statistiken - Tägliche Erinnerungen via lokale Notifications - Home-Screen-Widget (klein/mittel) mit App-Group-Datenaustausch
49 lines
1.7 KiB
Swift
49 lines
1.7 KiB
Swift
import Foundation
|
|
import UserNotifications
|
|
|
|
@MainActor
|
|
enum NotificationManager {
|
|
/// Default reminder time (09:00) used when the user first enables a reminder.
|
|
static var defaultTime: Date {
|
|
Calendar.current.date(bySettingHour: 9, minute: 0, second: 0, of: .now) ?? .now
|
|
}
|
|
|
|
@discardableResult
|
|
static func requestAuthorization() async -> Bool {
|
|
do {
|
|
return try await UNUserNotificationCenter.current()
|
|
.requestAuthorization(options: [.alert, .sound, .badge])
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
/// Cancels any existing reminder for the habit and, if it has a reminder
|
|
/// time, schedules a new daily notification.
|
|
static func reschedule(for habit: Habit) {
|
|
let center = UNUserNotificationCenter.current()
|
|
let id = identifier(for: habit)
|
|
center.removePendingNotificationRequests(withIdentifiers: [id])
|
|
|
|
guard let time = habit.reminderTime else { return }
|
|
|
|
let content = UNMutableNotificationContent()
|
|
content.title = habit.name
|
|
content.body = "Zeit für deine Gewohnheit"
|
|
content.sound = .default
|
|
|
|
let components = Calendar.current.dateComponents([.hour, .minute], from: time)
|
|
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
|
|
let request = UNNotificationRequest(identifier: id, content: content, trigger: trigger)
|
|
center.add(request)
|
|
}
|
|
|
|
static func cancel(for habit: Habit) {
|
|
UNUserNotificationCenter.current()
|
|
.removePendingNotificationRequests(withIdentifiers: [identifier(for: habit)])
|
|
}
|
|
|
|
private static func identifier(for habit: Habit) -> String {
|
|
"habit-\(habit.uuid.uuidString)"
|
|
}
|
|
}
|