LoginSignup
1
1

More than 3 years have passed since last update.

UIAlertControllerにUIProgressViewを追加してKVO監視更新

Last updated at Posted at 2019-07-30

データ変換をするクラスを作って、処理中にその中で変更される進捗度合いを、KVOで UIAlertController上のUIProgressViewに反映させます。

最初、進捗に応じた UIProgressView の表示更新ができなかったんですが、以下のように
表示側には DispatchQueue.main.async(flags: .barrier) {}
処理側には、 DispatchQueue.global(qos: .background).async {}を入れることで解決できました。

// progressView と _observer はメンバ変数

let progressAlert = UIAlertController(title: "Please wait", message: "Converting from old to new", preferredStyle: .alert)
self.progressView.progress = 0.0
progressAlert.view.addSubview(self.progressView)

// UIAlertControllerの高さ変更とUIProgressViewの配置
let height:NSLayoutConstraint = NSLayoutConstraint(item: progressAlert.view!,
                                                   attribute: NSLayoutConstraint.Attribute.height,
                                                   relatedBy: NSLayoutConstraint.Relation.equal,
                                                   toItem: nil,
                                                   attribute: NSLayoutConstraint.Attribute.notAnAttribute,
                                                   multiplier: 1, constant: 100)
progressAlert.view.addConstraint(height)
self.progressView.translatesAutoresizingMaskIntoConstraints = false
self.progressView.leadingAnchor.constraint(equalTo: progressAlert.view.leadingAnchor, constant: 10.0).isActive = true
self.progressView.trailingAnchor.constraint(equalTo: progressAlert.view.trailingAnchor, constant: -10.0).isActive = true
self.progressView.topAnchor.constraint(equalTo: progressAlert.view.topAnchor, constant: 65.0).isActive = true
self.progressView.heightAnchor.constraint(equalToConstant: 2.0)

// present と observe 設定と終了処理
present(progressAlert, animated: true, completion: {
    let dataMigration = DataMigration()
    self._observer = dataMigration.observe(\.dataProgress, options: .new) { object, change in
         DispatchQueue.main.async(flags: .barrier) {
            self.progressView.setProgress(object.dataProgress, animated: true)
        }
    }
    dataMigration.convert(何かオプション, completionHandler: {(sucess)->Void in
        self._observer = nil
        if sucess {
            print("Convert Complete")
        } else {
            print("Error")
        }
        progressAlert.dismiss(animated: true, completion: {
            ... 終了時の処理 ...
        })
    })
})

observeをするためには、DataMigrationは NSObjectのサブクラスでなければなりません。

class DataMigration: NSObject {
    @objc dynamic var dataProgress: Float = 0.0

    func convert(options: [Any], compleationHandler:@escaping ((_ success: Bool) -> Void) ) {
        var numberOfData: Float = ...データの個数...
        var countData: Float = 0.0
        DispatchQueue.global(qos: .background).async {
            for ...numberOfData分の繰り返し... {
                ...何か処理...
                countData += 1
                self.dataProgress = countData / numberOfData
            }
            completionHandler(true)
        }
    }
}

参考にしたのは下記です。
StackOverflow: Add Progress bar to UIAlertController with showing update

1
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
1
1