- イベント行にポップアップによる詳細ビュー(EventDetailView)を追加し、イベントの場所・メモ・URLなどをリッチに表示 - ボタン化によりイベントタップ時の操作性を改善 - NotificationCenterでNSCalendarDayChangedに対応し、日付変更時にイベントリストを自動更新するよう拡張 - 日時や区切りの表示、日本語ロケールへの対応などイベント詳細情報のUIを最適化
105 lines
2.9 KiB
Swift
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 }
|
|
}
|
|
}
|