search
LoginSignup
10

More than 1 year has passed since last update.

posted at

updated at

swiftのextensionによるローディングインジケータ共通化

全画面で共通のローディングインジケータを実装したい

UI操作ブロックする系のこういうのを全画面でいつでも呼び出せるようにしたい
Simulator Screen Shot - iPhone 8 - 2018-08-26 at 22.50.01.png

せっかくswiftだからUIViewControllerのextensionで書きたい

BaseViewController的なクラスに共通関数作って継承させていくのはSwiftyじゃない気がするので、UIViewControllerのextensionで実現させたい。。。

Swiftのextensionはストアドプロパティを持てない

最初にやろうとしたのは以下の方法 ※もちろんビルドエラー
swiftのextensionはコンピューテッドプロパティしか持てない為、このアプローチの仕方はできません

UIViewController+Extension.swift

extension UIViewController {

    let indicatorView = UIActivityIndicatorView.init(activityIndicatorStyle: .whiteLarge)
    let grayOutView = UIView(frame: self.view.frame)

    func startIndicator() {
        loadingIndicator.center = self.view.center
        grayOutView.backgroundColor = .black
        grayOutView.alpha = 0.6
        self.view.addSubview(grayOutView)
        self.view.addSubview(loadingIndicator)
        self.view.bringSubview(toFront: grayOutView)
        self.view.bringSubview(toFront: loadingIndicator)

        loadingIndicator.startAnimating()
    }

    func dismissIndicator() {
        indicatorView.removeFromSuperView()
        grayOutView.removeFromSuperView()
    }
}

最終的な実装方法

UIViewのtagプロパティを利用し、識別して表示、非表示
すごく単純に、かぶらなそうな値を割り振って処理するだけ(今回は999を使用)

UIViewController+Extension.swift
extension UIViewController {

    func startIndicator() {

        let loadingIndicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)

        loadingIndicator.center = self.view.center
        let grayOutView = UIView(frame: self.view.frame)
        grayOutView.backgroundColor = .black
        grayOutView.alpha = 0.6

        // 他のViewと被らない値を代入
        grayOutView.tag = 999

        grayOutView.addSubview(loadingIndicator)
        self.view.addSubview(grayOutView)
        self.view.bringSubviewToFront(grayOutView)

        loadingIndicator.startAnimating()
    }

    func dismissIndicator() {
        self.view.subviews.first(where: { $0.tag == 999 })?.removeFromSuperview()
    }

}

使用方法

SampleViewController.swift

    func sampleFunc() {
        // ローディング開始
        startIndicator()
        DispatchQueue.global(qos: .default).async {
            // 重い処理や通信処理
            DispatchQueue.main.async {
                // ローディング非表示
                self.dismissIndicator()
            }
        }
    }

もっとスマートなやり方募集中

swiftのextensionで書くって目的は達成されましたが、個人的にtagで判定ってのがしっくり来てないので、
もっといい方法あるよ!って方いらしたらコメントお願いしまーす!

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
What you can do with signing up
10