【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を使用して選択された日時に通知を登録する場合は注意が必要です。
VStack {
DatePicker("Date",
selection: $selectedDate,
in: dateRange,
displayedComponents: [.date]
).environment(\.locale, Locale(identifier: "ja_JP"))
.environment(\.calendar, Calendar(identifier: .japanese))
}
上記のように明示的に暦法を和暦(.japanese
)を指定している場合、使用する端末自体の暦法も和暦になっていないと通知が届きませんでした。(以下は変更後ですが、西暦の場合は届きませんでした)
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。
私がSwift UI学習に使用した参考書