SwiftUIで予定(カレンダー)を取得する方法

この記事は約9分で読めます。

SwiftUIでカレンダーの情報を取得する方法を紹介します。

取得する情報

  • iPhoneのカレンダーに設定されたイベント

作成した画面

コード例

コード例では以下のように単純にイベントを取得する処理のみを行なっています。

  • カレンダーのイベントを取得する期間をユーザーが日時で指定
  • ボタンを押すとユーザーが指定した日時のイベントをリストにして表示
import SwiftUI
import EventKit//①EventKitのフレームワークをインポートする

struct Calender: View {
    @State var ekEventStore = EKEventStore()//②EKEventStoreのオブジェクトを生成する
    @State var events: [EKEvent] = [EKEvent]()//カレンダーに設定されているイベントを取り込むプロパティ
    @State var authStatus: EKAuthorizationStatus = .notDetermined//アクセス許可の状態
    //以下はカレンダーを取得する開始日と終了日の設定用
    @State var startDate = Date()
    @State var endDate = Date()
    var body: some View {
        VStack {
            //予定を取り込む日時を設定
            InputDate(startDate: $startDate, endDate: $endDate)
                .padding()
            //カレンダー取得処理を行うボタン
            Button("カレンダーを取り込む") {
                Task {
                    //③アクセス許可のリクエスト
                    await getRequestAccess()
                    authStatus = EKEventStore.authorizationStatus(for: .event)
                    if authStatus == .authorized {
                        //④リクエストが完了したらカレンダーからイベントを取得する
                        events = getCalenderEvent()
                    }
                }
            }
            //アクセス許可の状態によって表示する内容を変える
            switch authStatus {
            case .authorized://承認された時
                List {
                    //⑤ ④で取得したイベントを全て表示する
                    ForEach(events, id: \.self) { event in
                        HStack {
                            Text(event.title)
                            Text("\(event.startDate)")
                            Text("\(event.endDate)")
                        }
                    }
                }
            case .denied:
                Text("アクセスが拒否されました")
            case .notDetermined:
                Text("アクセスが許可を待っています")
            case .restricted:
                Text("アクセスの制限がかかっています")
            @unknown default://何らかのエラー
                fatalError()
            }
        }
    }
    /*-----------------------*/
    /*アクセス許可のリクエスト処理*/
    /*-----------------------*/
    func getRequestAccess() async {
        //承認ステータスをチェックし承認以外ならリクエスト処理をする
        if EKEventStore.authorizationStatus(for: .event) != .authorized {
            do {
                //リクエストアクセスが完了するまで待つ
                try await ekEventStore.requestAccess(to: .event)
            }
            catch {
                //とりあえずの例外処理
                fatalError()
            }
        }
    }
    /*-----------------------*/
    /*カレンダーのイベント取得処理*/
    /*-----------------------*/
    func getCalenderEvent() -> [EKEvent] {
        var events = [EKEvent]()
        //全てのカレンダーを取得
        let calendars = ekEventStore.calendars(for:.event)
        //イベント取得時の絞り込み
        //入力した開始日と終了日の間にあるイベントを取得する
        let predicate = ekEventStore.predicateForEvents(withStart: startDate, end: endDate, calendars: calendars)
        events = ekEventStore.events(matching: predicate)
        
        return events
    }
}
//参考:カレンダーの取得日時を設定するためのビュー
struct InputDate: View {
    @Binding var startDate: Date
    @Binding var endDate: Date
    var body: some View {
        VStack {
            DatePicker("開始日時", selection: $startDate)
            DatePicker("終了日時", selection: $endDate)
        }
    }
}

コードの説明

カレンダー情報の取得でポイントとなる部分を説明します。

①EventKitのフレームワークをインポートする

カレンダーにアクセスするために、EventKitフレームワークをインポートしています。

②EKEventStoreのインスタンスを作成

EventKitをインポートしたことで、EKEventStoreのクラスを使用できるようになります。
EKEventStoreは、カレンダーやリマインダーの情報を扱っているクラスで、カレンダーにアクセスするために必要な機能を提供してくれています。

③アクセス許可のリクエスト

コード例ではボタンを押したときに「アクセス許可」→「カレンダーのイベントを取得」という処理を行なっています。

なお、アクセス許可をリクエストする際には、Custom iOS Target Propertiesへ設定追加する事前の準備が必要です

iPhoneなどのカレンダーから情報を取得するためには、iPhoneのユーザーの許可が必要となります。

アクセス許可に関する処理をgetRequestAccessとして関数にしていますので、参考にしてください。以下がアクセス許可をリクエストする部分です。

try await ekEventStore.requestAccess(to: .event)

requestAccessに戻り値はありませんが、アクセス許可が得られると以下の「authorizationStatus」(承認ステータスのようなもの)が承認済みの状態に変わります。

EKEventStore.authorizationStatus

承認ステータスを監視して、カレンダーの情報を表示するか判定するようにしています。

④カレンダーのイベントを取得

アクセス許可が完了したら、getCalenderEvent部分でカレンダーの情報を取得しています。

ekEventStore.calendars(for:.event)

上記でカレンダー情報の配列をゲットし、そのカレンダーに設定されているイベントを戻り値として返しています。

⑤イベントをリストにして表示

最後に取得したイベントをリストとして表示しているだけです。
表示している情報は、イベントのタイトルと、開始日、終了日です。

Custom iOS Target Propertiesへ設定追加

カレンダーなどiPhoneのユーザーデータにアクセスするためには、ユーザーからアクセス許可を得る必要があります。

アクセス許可の処理を実装するために、Custom iOS Target Propertiesに以下の「Property List Key」を設定します。
Custom iOS Target Propertiesは、iOS12以前では、Info.plistに代わる設定です。

Privacy - Calendars Usage Description

なお、Value欄にアクセス許可のダイアログが表示された際のメッセージを設定します。

難しそうだがまとめると簡単に見える

Custom iOS Target Propertiesへの設定や、アクセス許可の状態が変化するタイミング(一部非同期に処理が動作する部分がある)に注意が必要ですが、まとめてみると簡単に見えるのではないでしょうか。

よければ参考にしてください。

メモ

実際、アクセス許可のリクエストを出してから承認の状態が変わるまで非同期に変化する部分があり、詰まった時がありました。(try await ekEventStore.requestAccess(to: .event)←この部分をちょっと注意した方がいいかも)

タイトルとURLをコピーしました