swift初心者です。
http通信を行ってデータをダウンロードする処理を書いているのですが、ダウンロードに失敗した時、シンプルなアラートを表示したいと考えていますが、なかなかうまくいきません。
試したこと①
※alert(msg: )はアラート用に作った関数です。
swift
1 2func httpRequest(urlst: String) { 3 var req = URLRequest(url: URL(string: urlst)!) 4 req.httpMethod = "GET" 5 let task = URLSession.shared.dataTask(with: req, completionHandler: { data, response, error in 6 if error != nil { 7 self.alert(msg: "接続失敗") 8 return 9 } 10 }) 11} 12
これではアラートは出ませんでした。
試したこと②
swift
1override func viewWillAppear(_ animated: Bool) { 2 alertSignal = { (signal: Int) -> Void in 3 switch signal { 4 case: 0: 5 self.alert(msg: "接続失敗") 6 default: 7 break 8 } 9 } 10} 11 12var alertSignal: ((Int) -> Void)? 13 14func httpRequest(urlst: String) { 15 var req = URLRequest(url: URL(string: urlst)!) 16 req.httpMethod = "GET" 17 let task = URLSession.shared.dataTask(with: req, completionHandler: { data, response, error in 18 if error != nil { 19 self.alertSignal?(0) 20 return 21 } 22 }) 23} 24
これでも特に何も起こりませんでした。
試したこと③
swift
1override func viewWillAppear(_ animated: Bool) { 2 let notification = NotificationCenter.default 3 notification.addObserver(self, selector:#selector(severError(notification:)), name:Notification.Name(rawValue: "0"), object: nil) 4 5} 6 7@objc func serverError(notification: Notification) { 8 self.alert(msg: "接続失敗") 9} 10 11 12func httpRequest(urlst: String) { 13 var req = URLRequest(url: URL(string: urlst)!) 14 req.httpMethod = "GET" 15 let task = URLSession.shared.dataTask(with: req, completionHandler: { data, response, error in 16 if error != nil { 17 NotificationCenter.default.post(name: Notification.Name(rawValue: "0"), object: nil) 18 return 19 } 20 }) 21}
試したこと④
swift
1class ViewController: UIViewController, URLSessionTaskDelegate { 2 3 func httpRequest(urlst: String) { 4 var req = URLRequest(url: URL(string: urlst)!) 5 req.httpMethod = "GET" 6 let task = URLSession.shared.dataTask(with: req, completionHandler: { data, response, error in 7 //成功した場合のいろいろな処理 8 }) 9} 10 11func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { 12 DispathQueue.main.async { 13 self.alert(msg: "接続失敗") 14} 15} 16} 17
このように、いろいろ試してみましたが、アラートは表示されませんでした。
解決への糸口をご存じの方がいらっしゃれば、よろしくお願いいたします。
追記
alert関数の中身はこんな感じになっています。
swift
1func alert(msg: String) { 2 let alert = UIAlertController(title: nil, message: msg, preferredStyle: .alert) 3 let cancel: UIAlertAction = UIAlertAction(title: "OK", style: .cancel, handler: nil) 4 alert.addAction(cancel) 5 present(alert:, animated: true, completion: nil) 6} 7
さらに追記
調べたところ、どうやらアラートを呼び出している最中にアラートを呼び出しているのが問題のようでした。
関係ないだろうと質問を省いていました、申し訳ございません。
swift
1 2@IBAction func Button(_ sender: Any) { 3 let alert = UIAlertController(title: nil, message: msg, preferredStyle: .alert) 4 let next: UIAlertAction = UIAlertAction(title: "次へ", style: .default, handler: {(action: UIAlertAction) -> Void in 5 httpRequest(urlst: "http://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") 6}) 7 let cancel: UIAlertAction = UIAlertAction(title: "OK", style: .cancel, handler: nil) 8 alert.addAction(cancel) 9 alert.addAction(next) 10 present(alert, animated: true, completion: nil) 11} 12 13func httpRequest(urlst: String) { 14 var req = URLRequest(url: URL(string: urlst)!) 15 req.httpMethod = "GET" 16 let task = URLSession.shared.dataTask(with: req, completionHandler: { data, response, error in 17 DispathQueue.main.async { 18 self.alert(msg: "接続失敗") 19 } 20 }) 21 task.resume() 22} 23 24func alert(msg: String) { 25 let alert = UIAlertController(title: nil, message: msg, preferredStyle: .alert) 26 let cancel: UIAlertAction = UIAlertAction(title: "OK", style: .cancel, handler: nil) 27 alert.addAction(cancel) 28 present(alert, animated: true, completion: nil) 29} 30
「alert」とういうのが何なのか分かりませんが、その呼び出しの代わりに print("接続失敗") として表示されるのであれば、alert(msg:) の呼び出しをメインスレッドで行ってみて下さい。
可能であれば alert 関数も見たいですね。
alert(msg:)はUIAlertControllerを表示テキストだけ変えて使いまわすように作った関数です。
中身は
let alert = UIAlertController(title: msg,... ~~ present(alert, animated: true, completion: nil)
といった内容です。
メインスレッドで呼び出す、ということは、
https://developer.apple.com/documentation/code_diagnostics/main_thread_checker
上記のページに載っているように
DispathQueue.main.async { code }
を、completionHandlerの中で行えばいいということでしょうか。
そうです。(聞く前に試しましょう)
試してみて、やはり表示されないので不思議だと思ってデバッグエリアをよくよく見てみたら、すでにアラートが表示されているといった内容の文章を見つけました。実は、関係ないと思い込んで質問では省きましたが、関数httpRequestは、画面配置したボタン押下時、確認のアラートを表示してOKが押されたときに呼びされるという書き方をしていました。アラートコントローラーはすでに一つ呼び出されていると次のアラートが呼び出せないようになっている?ようでした。
どうやら自分の問題はこっちにあるようです。こちらの方向で、もう一度調べなおしてみます。
ちなみにprint文は表示されてたんですよね?表示は一回だけでしたか?
あと、present(alert:completion:)の中身も教えて下さい。
print文は表示されていました。表示も一回だけです。
もう修正中かもしれませんが、とりあえず原因を特定させたいのであれば、sleep()を挟むとか、asyncの代わりにasyncAfterを使うなど、エラー用Alertの表示を遅らせてみてはどうでしょうか。
回答3件
あなたの回答
tips
プレビュー