#全画面で共通のローディングインジケータを実装したい
UI操作ブロックする系のこういうのを全画面でいつでも呼び出せるようにしたい
せっかく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で判定ってのがしっくり来てないので、
もっといい方法あるよ!って方いらしたらコメントお願いしまーす!