Created
November 11, 2019 05:53
-
-
Save ha1f/56be93ee01622a70790f6ccfbbb3ccb5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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