【SwiftUI】通知を日付(Date型)で指定する方法!UNCalendarNotificationTrigger

この記事からわかること

  • Swiftプッシュ通知実装する方法
  • 通知を日付(Date)で指定するには?
  • UNCalendarNotificationTrigger使い方注意点
  • DateComponents使用方法
  • Date型からDateComponentsに変換すると通知が表示されない原因解決法
  • 端末設定により原因解決法

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

Swiftでプッシュ通知を表示させる日付や時間を直感的にDate型などで指定する方法をまとめていきます。この記事では通知の実装方法は解説しませんので下記記事を参考にしてください。

通知を日付(Date型)で指定する方法

通知機能を実装する際に通知の表示タイミングをUNTimeIntervalNotificationTriggerクラスを使った現在時刻+秒数単位ではなく、日付形式で指定するためにはUNCalendarNotificationTriggerを使用します。まずは使用例を見てみます。

UNTimeIntervalNotificationTriggerを使用した現在時刻+3秒後に通知表示

func sendNotificationRequest(){
    let content = UNMutableNotificationContent()
    content.title = "通知のタイトル"
    content.body = "通知の内容です"

    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)

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

UNCalendarNotificationTriggerを使用した8:30に通知表示

func sendNotificationRequest(){
    let content = UNMutableNotificationContent()
    content.title = "通知のタイトル"
    content.body = "通知の内容です"

    let dateComponent = DateComponents(hour: 8, minute: 30)
    let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: false)

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

UNCalendarNotificationTrigger

UNCalendarNotificationTrigger通知のトリガー条件を日付単位で指定できるクラスです。引数にはDate型ではなくDateComponents型で日付情報を渡します。

init(
    dateMatching dateComponents: DateComponents,
    repeats: Bool
)

【Swift】DateComponentsとは?使用方法とDate型との違い

DateComponents型はインスタンス化時のイニシャライザによって値を定義できます。

DateComponents

DateComponents(year: 2022, month: 10, day: 4, hour: 10, minute: 30)

またはCalendar構造体のdateComponentsメソッドからも変換可能です。このメソッドだとDate型から直接変換することが可能です。

Calendar.current.dateComponents(in: TimeZone.current, from: Date())

Date型から変換すると通知が表示されない?

Calendar構造体のdateComponentsメソッドを使用して現在時刻+3秒を設定してUNCalendarNotificationTriggerの引数に渡してみましたが、うまく動作しませんでした。

func sendNotificationRequest(_ date:Date){
    let content = UNMutableNotificationContent()
    content.title = "通知のタイトル"
    content.body = "通知の内容です"
    
    var dateComponent = Calendar.current.dateComponents(in: TimeZone.current, from: Date())
    dateComponent.second! += 3
    print(dateComponent) // 以下に表示
    let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: false)
    let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
    UNUserNotificationCenter.current().add(request)
}

この原因はUNCalendarNotificationTriggerの引数dateMatchingの説明に記述されていました。

引用:init(dateMatching dateComponents: DateComponents,repeats: Bool)

”dateComponents
トリガーを構築するときに使用する一時的な情報。トリガーに関連する日付コンポーネントのみを指定してください。”

引数として指定するDateComponentsは必要な情報のみを保持したデータでないといけないようです。先ほどのデータを表示して見るとさまざまな情報を保持してしまっているので正常に動作しなかったのだと思います。

calendar: gregorian (current) timeZone: Asia/Tokyo (fixed (equal to current)) era: 1 year: 2022 month: 10 day: 4 hour: 6 minute: 23 second: 41 nanosecond: 184649944 weekday: 3 weekdayOrdinal: 1 quarter: 0 weekOfMonth: 2 weekOfYear: 41 yearForWeekOfYear: 2022 isLeapMonth: false 

Date型から変換するには?

Date型から変換した情報を使用するためには以下のように配列形式で必要な情報を指定することで解決できました。

func sendNotificationRequest(){
    let content = UNMutableNotificationContent()
    content.title = "通知のタイトル"
    content.body = "通知の内容です"

    let dateComponent = Calendar.current.dateComponents([.hour,.minute,.second], from: Date())
    dateComponent.second! += 3
    print(dateComponent)  // 以下に表示
    let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: false)
    let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
    UNUserNotificationCenter.current().add(request)
}
hour: 6 minute: 32 second: 32 isLeapMonth: false 

端末の設定で通知が届かない?

Calendar.current.dateComponents([.hour,.minute,.second], from: Date())

上記のような場合は良かったのですが、例えばDatePickerを使用して選択された日時に通知を登録する場合は注意が必要です。

SwiftUIで日付をカレンダーから選択する方法
VStack {
    DatePicker("Date",
                selection: $selectedDate,
                in: dateRange,
                displayedComponents: [.date]
    ).environment(\.locale, Locale(identifier: "ja_JP"))
    .environment(\.calendar, Calendar(identifier: .japanese))
}

上記のように明示的に暦法を和暦(.japanese)を指定している場合、使用する端末自体の暦法も和暦になっていないと通知が届きませんでした。(以下は変更後ですが、西暦の場合は届きませんでした)

【SwiftUI】通知を日付(Date型)で指定する方法!UNCalendarNotificationTrigger

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

私がSwift UI学習に使用した参考書

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index