もくじ
どうもこんにちは。iOSをメインに開発しているロッキーカナイです。
今日はUIImageViewを継承して、非同期通信で画像を取得し表示してみたいと思います。テーブルセルなんかでよくある、クルクルしてから画像を表示するアレです。といってもAlamofireやAFNetworkingなんかのライブラリを使って簡単に実装できるのですが、標準フレームワークで作ってみたので紹介します。
コード
class UriImageView: UIImageView {
// タイムアウトの設定
let TIME_OUT: TimeInterval = 1 * 60
// インジケータの初期化
let indicator: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray)
override init(frame: CGRect) {
super.init(frame: frame)
createIndicator()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
createIndicator()
}
/// クルクルするインジケータの生成
func createIndicator() {
indicator.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
indicator.hidesWhenStopped = true
self.addSubview(indicator)
}
/// urlImage
/// - parameter urlString: 画像url
/// - returns: nil
func urlImage(urlString: String){
// インジケータアニメーションの開始
indicator.startAnimating()
// URLRequestの生成
let req = URLRequest(url: NSURL(string:urlString)! as URL,
cachePolicy: .returnCacheDataElseLoad,
timeoutInterval: TIME_OUT)
let conf = URLSessionConfiguration.default
// URLSessionの生成
let session = URLSession(configuration: conf, delegate: nil, delegateQueue: OperationQueue.main)
session.dataTask(with: req, completionHandler:
{ data, resp, err in
// 通信結果
if err == nil {
// Success
let image = UIImage(data:data!)
self.image = image
}else{
// Error
self.image = UIImage(named: "error")
}
// インジケータアニメーションの終了
self.indicator.stopAnimating()
}).resume()
}
}
呼び出し
image.urlImage(urlString: "http://~~~.png")
取得urlがhttpsであればよいのですが、httpで始まるurlの場合はinfo.plistにhttpを使う旨の登録が必要です。
App Transport Security Settings – Dictionary
Allow Arbitrary Loads – Boolean – YES
解説
組み込みたかった動作としては3点です。
- 通信中はインジケータ(クルクル)を表示させる
- 非同期通信する
- 通信エラー時は分かり易いようにエラー画像を表示させる
今回画像を非同期取得をする必要があったので、UIImageViewクラスを継承させて、そこに非同期通信させる制御を追加しました。
サンプル動画
取得成功時の動画です。
エラー時です。
おわり
非同期で取得というと、なんだか難しく感じるかもしれませんが、このように簡単に出来ました。今日のちょい足しは「非同期通信で画像を取得し表示させるUIImageViewを作ってみる」でした。