Files
ore-calendar/Sources/CalendarService.swift
ssig33 b8dd3e254d イベント詳細表示と日付変更検知によるカレンダーのUX向上
- イベント行にポップアップによる詳細ビュー(EventDetailView)を追加し、イベントの場所・メモ・URLなどをリッチに表示
- ボタン化によりイベントタップ時の操作性を改善
- NotificationCenterでNSCalendarDayChangedに対応し、日付変更時にイベントリストを自動更新するよう拡張
- 日時や区切りの表示、日本語ロケールへの対応などイベント詳細情報のUIを最適化
2025-10-24 23:30:27 +09:00

105 lines
2.9 KiB
Swift

import EventKit
import Foundation
class CalendarService: ObservableObject {
private let eventStore = EKEventStore()
@Published var events: [EKEvent] = []
@Published var selectedCalendars: Set<String> = []
@Published var availableCalendars: [EKCalendar] = []
@Published var hasAccess = false
init() {
Task {
await requestAccess()
}
setupNotificationObserver()
}
deinit {
NotificationCenter.default.removeObserver(self)
}
private func setupNotificationObserver() {
NotificationCenter.default.addObserver(
forName: .EKEventStoreChanged,
object: eventStore,
queue: .main
) { [weak self] _ in
self?.handleEventStoreChanged()
}
NotificationCenter.default.addObserver(
forName: .NSCalendarDayChanged,
object: nil,
queue: .main
) { [weak self] _ in
self?.handleDayChanged()
}
}
@MainActor
private func handleEventStoreChanged() {
loadCalendars()
loadEvents()
}
@MainActor
private func handleDayChanged() {
loadEvents()
}
@MainActor
func requestAccess() async {
do {
let granted = try await eventStore.requestFullAccessToEvents()
hasAccess = granted
if granted {
loadCalendars()
loadDefaultSelectedCalendars()
loadEvents()
}
} catch {
print("Calendar access error: \(error)")
hasAccess = false
}
}
@MainActor
func loadCalendars() {
availableCalendars = eventStore.calendars(for: .event)
}
@MainActor
func loadDefaultSelectedCalendars() {
if let savedCalendars = UserDefaults.standard.array(forKey: "selectedCalendars") as? [String] {
selectedCalendars = Set(savedCalendars)
} else {
selectedCalendars = Set(availableCalendars.map { $0.calendarIdentifier })
}
}
@MainActor
func saveSelectedCalendars() {
UserDefaults.standard.set(Array(selectedCalendars), forKey: "selectedCalendars")
loadEvents()
}
@MainActor
func loadEvents() {
let calendar = Calendar.current
let today = calendar.startOfDay(for: Date())
guard let startDate = calendar.date(byAdding: .day, value: -14, to: today),
let endDate = calendar.date(byAdding: .day, value: 14, to: today) else {
return
}
let calendars = availableCalendars.filter { selectedCalendars.contains($0.calendarIdentifier) }
let predicate = eventStore.predicateForEvents(withStart: startDate, end: endDate, calendars: calendars)
let fetchedEvents = eventStore.events(matching: predicate)
events = fetchedEvents.sorted { $0.startDate < $1.startDate }
}
}