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

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

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

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Swift

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

Q&A

解決済

3回答

3546閲覧

swiftで処理のタイムアウトを実現したい

HajimeHamada

総合スコア20

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

Swift

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

1グッド

1クリップ

投稿2018/02/27 09:18

編集2018/02/28 07:08

Swift3でiPhoneアプリを開発しています。ネットワークアクセスで時間のかかる可能性のある処理があり、それをある時間以上かかったらタイム・アウトしたいと思っています。

例えば、10秒後にある処理をしたければ、

Swift

1DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: { 2 (10秒後にやりたい処理) 3})

のように書けばいいかと思うのですが、10秒後にある処理をやめたい場合にはどのように書けばいいのでしょうか?

(追記) 2018.2.28
追記します。タイムアウトしたい処理は、Google Firebase Realtime DatabaseのobserveSingleEventです。コードは、以下のようになっています。

Swift

1let checkRef = Database.database().reference().child(Const.UpdatePath) 2checkRef.observeSingleEvent(of: DataEventType.value, with: { snapshot in 3 (snapshotを使った処理) 4}

よろしくお願いします。

fuzzball👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

ちょろ~っと調べておそらくこうするんだろうなぁという、全く試してもいない方法です。

swift

1 2var finished = false 3 4let checkRef = Database.database().reference().child(Const.UpdatePath) 5 6// キャンセル処理を入れるためobserveEventメソッドを使用 7let handler = checkRef.observeEvent(of: DataEventType.value, with: { snapshot in 8 if finished { return } 9 finished = true 10 11 defer { 12 checkRef.removeObserver(withHandle: handler) 13 } 14 15 (snapshotを使った処理) 16} 17 18// このメソッドをすぐに抜けるためのスレッド。すぐに抜ける必要がないならいらない 19DispatchQueue.global().async() { 20 let group = DispatchGroup() 21 22 // タイムアウト処理のためのスレッド 23 DispatchQueue.global().async(group: group) { 24 while !finished { } 25 } 26 27 // groupの処理待ち 28 if group.wait(wallTimeout: .now() + 10) == .timedOut { 29 30 // timeoutしたら監視をやめる 31 checkRef.removeObserver(withHandle: handler) 32 33 34 // Timeout時の処理 35 } 36} 37

投稿2018/03/03 03:51

MasakiHori

総合スコア3384

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

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

HajimeHamada

2018/03/03 04:39

少し試させていただいたところ、これで上手く行きそうです。handlerを使って処理するんですね。ありがとうございました。
guest

0

別スレッドで実行して、10秒後にスレッドごと削除してしまうとか。

【追記】

あまり深く考えずに作ったので参考程度に。

swift

1print("[main]", Thread.current) 2let thread = Thread(target: self, selector: #selector(hoge), object: nil) 3thread.start() 4print("start") 5DispatchQueue.main.asyncAfter(deadline: .now() + 10) { 6 print("cancel") 7 thread.cancel() 8} 9 10@objc func hoge() { 11 print("[hoge]", Thread.current) 12 while true { 13 print("thread =", Thread.current, Date()) 14 if Thread.current.isCancelled { 15 print("exit") 16 Thread.exit() 17 } 18 Thread.sleep(forTimeInterval: 3) 19 } 20}
[main] <NSThread: 0x17e64da0>{number = 1, name = main} [hoge] <NSThread: 0x17e87010>{number = 3, name = (null)} start 2018-02-28 09:01:08 +0000 2018-02-28 09:01:11 +0000 2018-02-28 09:01:14 +0000 2018-02-28 09:01:17 +0000 cancel exit

投稿2018/02/28 07:34

編集2018/02/28 09:02
fuzzball

総合スコア16731

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

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

HajimeHamada

2018/02/28 08:41

ご回答ありがとうございます。別スレッドでの処理はいいかもしれません。 以下のようなテストプログラムを書きました。 DispatchQueue(label: "jp.xxxxx.thread-test").async { print("start") sleep(10) print("10seconds after...") } DispatchQueue.main.asyncAfter(deadline: .now() + 5.0, execute: { print("5seconds after...") (スレッドの削除?) }) これで、"start"が印字されてから、5秒後に"5seconds after..."が印字されます。その後に、最初のスレッドを削除したいのですが、削除はどうすればいいんでしょう? 不勉強で申し訳ないですが、ご教示いただければ。
fuzzball

2018/02/28 16:56

直接スレッドをkillする方法が見つからなかったので、あまり意味のないサンプルコードになってしまいました。
HajimeHamada

2018/03/03 04:37

ありがとうございます。複数スレッドでの処理、参考になります。
guest

0

ネットワークアクセス中に10秒以上経過した場合にタイムアウトさせたいということでしょうか?

それでしたらURLSessionをお使いの場合、URLRequestでタイムアウトの設定ができます。

Swift

1 2let path = "https://XXXXXXX" 3let url = URL(string: path)! 4var request = URLRequest(url: url) 5 6// タイムアウトの時間を設定する 7request.timeoutInterval = 600 8 9let task = URLSession.shared.dataTask(with: request) { data, response, error in 10 11  // レスポンス処理 12} 13task.resume() 14

投稿2018/02/27 22:30

newmt

総合スコア1277

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

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

HajimeHamada

2018/02/28 06:59

回答ありがとうございます。URLSessionでのタイムアウト処理、勉強になります。残念ながら、今回のプログラムでは、タイムアウトしたいのは、Google Firebaseの処理になります。質問に追記いたしました。
newmt

2018/02/28 08:00

それでしたか。失礼致しました。 Firebaseはあまり使ったことはないのですが、 トークンを取得して10秒後に破棄するとかはできないのでしょうか? let checkRef = Database.database().reference().child(Const.UpdatePath) let handle = observe(.value) { (snapshot) in (snapshotを使った処理) } DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: { checkRef.removeObserverWithHandle(handle) })
HajimeHamada

2018/03/03 04:40

このままでは上手く動かないようでしたが、handlerを使って処理するというのは正解のようでした。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問