【Xcode/SwiftUI】シンプルなリマインダーを作ってUserNotificationsを学ぶ

Contents 非表示

実装

Model

import Foundation

struct Reminder: Identifiable {
    let id = UUID()
    let title: String
    let date: Date

    init(title: String, date: Date) {
        self.title = title
        self.date = date
    }
}

View

import SwiftUI

struct HomeView: View {
    @StateObject private var viewModel = ReminderViewModel()
    @State private var newReminderTitle = ""
    @State private var selectedDate = Date()

    var body: some View {
        NavigationView {
            VStack {
                if viewModel.notificationStatus == .notDetermined {
                    Button("Ask for Permission") {
                        viewModel.requestNotificationPermission()
                    }
                } else if viewModel.notificationStatus == .denied {
                    Text("Please enable notification permissions in Settings to use the reminder feature.")
                        .padding()
                } else {
                    List {
                        Section(header: Text("Reminders")) {
                            ForEach(viewModel.reminders) { reminder in
                                HStack {
                                    Text(reminder.title)
                                    Spacer()
                                    Text(formattedDate(reminder.date))
                                        .font(.subheadline)
                                }
                            }
                            .onDelete(perform: deleteReminder)
                        }
                        Section {
                            TextField("Enter reminder", text: $newReminderTitle)
                            DatePicker("Select Date", selection: $selectedDate, displayedComponents: [.date, .hourAndMinute])
                        }

                        Section {
                            Button("Add Reminder") {
                                let newReminder = Reminder(title: newReminderTitle, date: selectedDate)
                                viewModel.scheduleNotification(for: newReminder)
                                newReminderTitle = ""
                            }
                        }
                    }
                    .listStyle(InsetGroupedListStyle())
                }
            }
            .navigationTitle("Reminder App")
        }
    }

    private func deleteReminder(at offsets: IndexSet) {
        viewModel.reminders.remove(atOffsets: offsets)
    }

    private func formattedDate(_ date: Date) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .short
        dateFormatter.timeStyle = .short
        return dateFormatter.string(from: date)
    }
}

ViewModel

import SwiftUI
import UserNotifications

class ReminderViewModel: ObservableObject {
    @Published var reminders: [Reminder] = []
    @Published var notificationStatus: UNAuthorizationStatus = .notDetermined

    init() {
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            DispatchQueue.main.async {
                self.notificationStatus = settings.authorizationStatus
            }
        }
    }

    func requestNotificationPermission() {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
            DispatchQueue.main.async {
                self.notificationStatus = granted ? .authorized : .denied
            }
        }
    }

    func scheduleNotification(for reminder: Reminder) {
        let content = UNMutableNotificationContent()
        content.title = "Reminder"
        content.body = reminder.title
        content.sound = .default

        let dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: reminder.date)
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

        let request = UNNotificationRequest(identifier: reminder.id.uuidString, content: content, trigger: trigger)
        UNUserNotificationCenter.current().add(request)

        reminders.append(reminder)
    }
}