0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Swift × MVVM × RxSwift】Kingfisherで画像の切り替えの実装

Last updated at Posted at 2025-05-12

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を使用した非同期の画像取得に比べて手軽に実装ができます。
また様々な機能を備えているので使い勝手のいいライブラリだと思いました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?