Skip to content

Instantly share code, notes, and snippets.

@ha1f
Created November 11, 2019 05:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ha1f/56be93ee01622a70790f6ccfbbb3ccb5 to your computer and use it in GitHub Desktop.
Save ha1f/56be93ee01622a70790f6ccfbbb3ccb5 to your computer and use it in GitHub Desktop.
//
// WithBlockingView.swift
//
extension ObservableConvertibleType {
/// actionがcompleteするまで画面を表示する
func withBlockingView(from parentViewController: UIViewController) -> Observable<Element> {
let viewController = _BlockingLoadingViewController(self)
return viewController.result
.do(onSubscribed: { [weak parentViewController] in
DispatchQueue.main.async {
parentViewController?.present(viewController, animated: true, completion: nil)
}
})
}
}
/// 特定の操作のため、ブロックするための画面を出す。
/// 必ずcompleteさせること
private final class _BlockingLoadingViewController<T>: UIViewController {
private let _indicator = UIActivityIndicatorView(style: .gray)
private let disposeBag = DisposeBag()
private let _action: Observable<T>
private let _publisher = PublishSubject<T>()
fileprivate var result: Observable<T> {
return _publisher
.takeUntil(rx.deallocated)
}
init<O: ObservableConvertibleType>(_ action: O) where O.Element == T {
_action = action.asObservable()
super.init(nibName: nil, bundle: nil)
modalPresentationStyle = .overCurrentContext
modalTransitionStyle = .crossDissolve
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(displayP3Red: 1.0, green: 1.0, blue: 1.0, alpha: 0.7)
_indicator.hidesWhenStopped = true
view.addSubview(_indicator)
_indicator.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
_indicator.centerXAnchor.constraint(equalTo: view.centerXAnchor),
_indicator.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
_indicator.startAnimating()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
_action
.retryWhen({ [weak self] error -> Observable<Void> in
return error
.flatMap { _ in
return self?._showRetryAlert() ?? .empty()
}
})
.do(onCompleted: { [weak self] in
DispatchQueue.main.async {
self?.dismiss(animated: true, completion: nil)
}
})
.bind(to: _publisher)
.disposed(by: disposeBag)
}
private func _showRetryAlert() -> Observable<Void> {
let publisher = PublishSubject<Void>()
DispatchQueue.main.async { [weak self] in
let alertController = UIAlertController(title: "エラー", message: "再試行しますか?", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "キャンセル", style: .cancel, handler: { _ in
self?.dismiss(animated: true, completion: nil)
publisher.onCompleted()
}))
alertController.addAction(UIAlertAction(title: "再試行", style: .default, handler: { _ in
publisher.onNext(())
publisher.onCompleted()
}))
self?.present(alertController, animated: true, completion: nil)
}
return publisher
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment