質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

1243閲覧

[Swift]指定した曜日にXX時間ごとにアラームを発火させたい

Sagamaru

総合スコア70

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2021/05/25 11:33

編集2021/05/26 04:03

やりたいこと

以下のようなことができるiOSアプリをSwiftで作りたいと考えています(iPhoneで動くことを想定)。

金曜日の朝10時から夜21時まで1時間ごとにアラームを鳴らす

ユーザーは以下を指定できます

  • 曜日
  • 開始時刻
  • 終了時刻
  • アラームの繰り返し間隔(XX時間ごとに鳴る)

アラームが発火すると音が鳴ったり、バイブレーションが動くことを想定しています。

調べたこと

Timerクラス

Timerクラスを使って1秒ごとに時刻を表示するサンプルを作りました。
例えば定期的に現在時刻をチェックして、特定の日時になったらアラームを発火するということを行えば今回の仕様を満たせそうに思えました。しかし、アプリがバックグラウンドに行くとTimerクラスが停止して処理が動かないことがわかりました。バックグラウンド中でもアラームは鳴らしたいのですが、こちらでは実現できませんでした。

class TimerTest { var timer = Timer() var count = 0 var date: Date? func start(){ date = Date() // 1秒ごとに発火するタイマーを設定する timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.task), userInfo: nil, repeats: true) } func stop(){ timer.invalidate() } @objc func task() { guard let timeZoneJP = TimeZone(identifier: "Asia/Tokyo") else { return } guard let targetDate = date else { return } var calender = Calendar.current calender.timeZone = timeZoneJP // Dateを1秒づつ進める count += 1 let advanceDate = calender.date(byAdding: .second, value: count, to: targetDate)! // Dateから時刻に関係する各要素を取得する let comp = calender.dateComponents( [Calendar.Component.year, Calendar.Component.month, Calendar.Component.weekday, Calendar.Component.day, Calendar.Component.hour, Calendar.Component.minute, Calendar.Component.second], from: advanceDate) guard let year = comp.year else { return } guard let month = comp.month else { return } guard let day = comp.day else { return } guard let weekday = comp.weekday else { return } guard let hour = comp.hour else { return } guard let minute = comp.minute else { return } guard let second = comp.second else { return } print("年:(year) 月:(month) 日:(day) 曜日:(weekday) 時間:(hour) 分: (minute) 秒:(second)") } }

ローカル通知

アプリがバックグラウンド中でもアラームを発火させるためにローカル通知を検討しました。
こちらの2つのクラスに注目しました。

  • UNTimeIntervalNotificationTrigger
  • UNCalendarNotificationTrigger

UNTimeIntervalNotificationTriggerは引数に指定した時間ごとに通知を繰り返すことができ、UNCalendarNotificationTriggerは引数に指定した日付、曜日、時刻に通知することができることがわかりました。

しかし、今回私が求めている機能だとどちらを使っても仕様を満たせそうにありませんでした。

質問

Swiftの経験がほぼないこともあり調べても解決策が見つからず詰まっている状態です。
以下を実現するためにはどういう手段が考えられますでしょうか?
金曜日の朝10時から夜21時まで1時間ごとにアラームを鳴らす

お手数ですがご回答お待ちしております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tomato879241

2021/05/25 21:54

まずはDate()とTimerの使い方を勉強してください。 1. DateのtimeZoneを設定する。 2. Dateから時・分・秒・曜日を取得する。 3. Timerを使ってDateを1秒ごとに進める。 上の基本的なことができないと、「通知」を使う段階に進まないのでは?
Sagamaru

2021/05/25 22:42

回答ありがとうございます。「1」と「2」は既に試しており、ログ出力で期待通り日本時間で出力することを確認しております。「3」はやったことがなかったため「3」を理解してみます。理解したら、質問欄に理解したことを記載して更新致します。少々お待ちください。
Sagamaru

2021/05/26 04:11

tomato879241様。 こちらを勉強して理解しました。 調べたことに、ソースコードを記載しました。 ------------------------------------------ 1. DateのtimeZoneを設定する。 2. Dateから時・分・秒・曜日を取得する。 3. Timerを使ってDateを1秒ごとに進める。 ------------------------------------------ 実機で動作を見たのですが、アプリがバックグラウンドに行くとタイマーが停止して処理がうごきませんでした。アプリがバックグラウンドでもアラームを鳴らしたいのですが、現状手段が見つからず・・・。大変お手数ですが自分に足りない考え方、手段などありましたらご教示頂けると助かります。どうぞ宜しくお願いします。
tomato879241

2021/05/26 04:47

「様」付けはどうかやめてください。 あ〜、済みません。質問を端から端まで読んだか覚えていませんが、そのような機能をバックグラウンドで使えるようにするのは難しいです。まずは「Capability」の「Background mode」をオンにする必要がありますが、そもそもアプリがバックグラウンドで機能する理由(例えば、音楽を流す、アプリの所在地を追跡)がなければ、アプリは随時バックグラウンドで動いていることができません。詳しくは「Swift Timer Background」などで検索して、自分で調べてみてください。
Sagamaru

2021/05/26 09:04

情報ありがとうございます!「Swift Timer Background」でさっそく調べてみます。数日他の方から回答が来なかったり、調べた結果、実現不可能そうであればこちらの質問をクローズ致します。
guest

回答1

0

自己解決

色々調べましたがiOSのバックグラウンド制約の関係上求めていた挙動は厳しそうでした。

投稿2021/05/30 04:27

Sagamaru

総合スコア70

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問