iOSでサーバー上の画像データを取得し、UIImage型で返す関数を作っているのですが、うまく戻り値(UIImage)が渡せません。いま書いているコードは以下の通りです。
import UIKit class ViewController: UIViewController { @IBOutlet weak var imageView: UIImageView! override func viewDidLoad() { super.viewDidLoad() let pass = "https://*************/photo.jpg" if let result = getImage(pass: pass) { // ①ここだと表示されないけど… imageView.image = result } } // 画像を取得して返す func getImage(pass: String) -> UIImage? { var result = UIImage() if let url = URL(string: pass) { let request = URLRequest(url: url) let session = URLSession.shared let task = session.dataTask(with: request) { (data:Data?, response:URLResponse?, error:Error?) in if let data = data, let image = UIImage(data: data) { result = image } } task.resume() } /* ②ここに書くと表示されます DispatchQueue.main.async { self.imageView.image = result } */ return result } }
意図としては、getImage関数に画像パスを投げ、返ってきたUIImageを表示する、というシンプルなものです。ですが、①に書いた場合は表示されず、②の位置に書いた場合にのみ表示されます。返ってきたresultを①の位置でprintすると、一応UIImage型(<UIImage: 0x0000000000>のような表示)になっています。
戻り値をVoidにして②のように関数内で書いてしまってもいいのですが、それだと関数にした意味がなく、ファイルの切り分けができなくなるので…
こんな状況ですが、何かお気付きの点がございましたら、ご教授いただけますと幸いです。
よろしくお願いいたします。
追記
ご回答をもとに、修正してみました。
imageViewを引数として関数へ渡し、クロージャ内で表示させる方法です。
これなら怪しげな戻り値を経由させることなく、処理の汎用化もできそうです。
import UIKit class ViewController: UIViewController { @IBOutlet weak var imageView: UIImageView! override func viewDidLoad() { super.viewDidLoad() // 表示処理を呼ぶ let pass = "https://*************/photo.jpg" getImage(pass: pass, view: imageView) } // 画像を取得して表示 func getImage(pass: String, view: UIImageView) -> Void { if let url = URL(string: pass) { let request = URLRequest(url: url) let session = URLSession.shared let task = session.dataTask(with: request, completionHandler: { (data:Data?, response:URLResponse?, error:Error?) in if let data = data, let image = UIImage(data: data) { DispatchQueue.main.async { view.image = image } } }) task.resume() } } }
今回の質問を通して、dataTaskクロージャの正しい使い方を学ぶことができました。
こんなグズグズですが、わたしと同じように悩んでいるSwift初心者の方のお役に立てましたら幸いです。
今回のまとめ**「dataTaskの完了処理はcompletionHandlerの中に書く!」**
今さらすぎてお恥ずかしい限りですが、精進してまいりたいと思います。
回答2件
あなたの回答
tips
プレビュー