Kingfisherについて
Kingfisherは、URLから画像を簡単かつ高速にダウンロードし、キャッシュ機能を備えた柔軟な画像読み込みライブラリです。
参考文献
実際に使ってみる
完成イメージ
写真① | 写真② |
---|---|
![]() |
![]() |
ImageViewとButtonを用意します。
ボタンをタップしたら画像を切り替えるようにしてます。写真にはフリー素材のURLを使用しました。
※アプリ内で使用している画像は Unsplash から取得しています。
MVVM × RxSwiftでリアクティブに切り替えを行うよう書込みました。
1️⃣ImageURL(Model)
画像URLを列挙型で管理してます。
ImageURL
// 画像URLを管理するためのEnum
enum ImageURL {
case firstImage
case secondImage
var url: String {
switch self {
case .firstImage:
return "画像1のURL"
case .secondImage:
return "画像2のURL"
}
}
}
2️⃣ImageURLViewModel(ViewModel)
View側でのボタンタップ検知と、画像URLの取得・反映を担う橋渡し役です。
ImageURLViewModel
import Foundation
import RxSwift
import RxCocoa
protocol ImageURLViewModelInputs: AnyObject {
var buttonTap: PublishRelay<Void> { get }
}
protocol ImageURLViewModelOutputs: AnyObject {
var imageViewURLString: Driver<String> { get }
}
protocol ImageURLViewModelType: AnyObject {
var inputs: ImageURLViewModelInputs { get }
var outputs: ImageURLViewModelOutputs { get }
}
class ImageURLViewModel: ImageURLViewModelInputs, ImageURLViewModelOutputs, ImageURLViewModelType {
// MARK: - Properties
var inputs: ImageURLViewModelInputs { return self }
var outputs: ImageURLViewModelOutputs { return self }
// MARK: - Input Sources
let buttonTap = PublishRelay<Void>()
// MARK: - Output Sources
let imageViewURLString: Driver<String>
private let _imageViewURLString = BehaviorRelay<String>(value: ImageURL.firstImage.url)
private let disposeBag = DisposeBag()
// MARK: - Initialize
init() {
self.imageViewURLString = _imageViewURLString.asDriver(onErrorDriveWith: .empty())
buttonTap.asObservable()
.withLatestFrom(_imageViewURLString)
.map { currentURL in
return currentURL == ImageURL.firstImage.url ? ImageURL.secondImage.url : ImageURL.firstImage.url
}
.bind(to: _imageViewURLString)
.disposed(by: disposeBag)
}
}
3️⃣ImageURLViewController(View)
実際に画像を反映させる場所です。こちらでKingfisherを使って非同期に画像を表示させるようにしてます。
ImageURLViewController
import UIKit
import RxSwift
import RxCocoa
import Kingfisher
class ViewController: UIViewController {
// MARK: - Properties
@IBOutlet private weak var imageView: UIImageView!
@IBOutlet private weak var toggleImageButton: UIButton!
let viewModel = ImageURLViewModel()
private let disposeBag = DisposeBag()
// MARK: - Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
bind()
}
}
// MARK: - Binding
extension ViewController {
func bind() {
toggleImageButton.rx.tap
.subscribe(onNext: {
self.viewModel.inputs.buttonTap.accept(())
})
.disposed(by: disposeBag)
viewModel.outputs.imageViewURLString
.drive(onNext: { imageURL in
guard let url = URL(string: imageURL) else { return }
self.imageView.kf.setImage(with: url)
})
.disposed(by: disposeBag)
}
}
プレースホルダーとは?
またKingfisherの一つの機能でプレースホルダーを指定することができます。
プレースホルダーとは画像を読み込んでいる間に一時的に表示しておく仮の画像のことです。
[表示の流れ]
① ボタンタップ
↓
② 画像読み込み中...(ここでプレースホルダー画像を表示)
↓
③ ネットから画像が届く
↓
④ 本物の画像に差し替え!
プレースホルダーの指定方法
プレースホルダーはsetImage引数にplaceholderでURLを指定してあげることで簡単に使用できます。
viewModel.outputs.imageViewURLString
.drive(onNext: { imageURL in
guard let url = URL(string: imageURL) else { return }
self.imageView.kf.setImage(with: url,
placeholder: UIImage(named: "placeholder_image"))
})
.disposed(by: disposeBag)
まとめ
Kingfisherを使うことでURLSessionを使用した非同期の画像取得に比べて手軽に実装ができます。
また様々な機能を備えているので使い勝手のいいライブラリだと思いました。