mirror of
https://github.com/fxm90/GradientLoadingBar.git
synced 2026-06-16 12:24:31 +00:00
♻️ :: Moved logic for removing the gradientView from its superview on deinit to view-model and provide tests
This commit is contained in:
@@ -17,8 +17,6 @@ class GradientLoadingBarViewModelTestCase: XCTestCase {
|
||||
private var sharedApplicationMock: SharedApplicationMock!
|
||||
private var notificationCenter: NotificationCenter!
|
||||
|
||||
private var viewModel: GradientLoadingBarViewModel!
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
override func setUp() {
|
||||
@@ -26,14 +24,9 @@ class GradientLoadingBarViewModelTestCase: XCTestCase {
|
||||
|
||||
sharedApplicationMock = SharedApplicationMock()
|
||||
notificationCenter = NotificationCenter()
|
||||
|
||||
viewModel = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
|
||||
notificationCenter: notificationCenter)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
viewModel = nil
|
||||
|
||||
notificationCenter = nil
|
||||
sharedApplicationMock = nil
|
||||
|
||||
@@ -73,16 +66,22 @@ class GradientLoadingBarViewModelTestCase: XCTestCase {
|
||||
keyWindow)
|
||||
}
|
||||
|
||||
func testInitializerShouldSetupSuperviewObservableAfterUIWindowDidBecomeKeyNotificationJustOnce() {
|
||||
func testDeinitShouldResetSuperviewObservableToNil() {
|
||||
// Given
|
||||
let viewModel = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
|
||||
notificationCenter: notificationCenter)
|
||||
let keyWindow = UIWindow()
|
||||
sharedApplicationMock.keyWindow = keyWindow
|
||||
|
||||
let expectation = self.expectation(description: "Expected observer for superview to be informed just once.")
|
||||
// swiftlint:disable:next unnecessary_type
|
||||
var viewModel: GradientLoadingBarViewModel? = GradientLoadingBarViewModel(sharedApplication: sharedApplicationMock,
|
||||
notificationCenter: notificationCenter)
|
||||
|
||||
let expectation = self.expectation(description: "Expected observer to be informed to reset superview to nil.")
|
||||
|
||||
var disposeBag = DisposeBag()
|
||||
viewModel.superview.subscribe { newSuperview, _ in
|
||||
guard newSuperview != nil else {
|
||||
|
||||
// swiftlint:disable:next force_unwrapping
|
||||
viewModel!.superview.subscribe { newSuperview, _ in
|
||||
guard newSuperview == nil else {
|
||||
// Skip initial call to observer.
|
||||
return
|
||||
}
|
||||
@@ -91,11 +90,7 @@ class GradientLoadingBarViewModelTestCase: XCTestCase {
|
||||
}.disposed(by: &disposeBag)
|
||||
|
||||
// When
|
||||
for _ in 1 ... 3 {
|
||||
sharedApplicationMock.keyWindow = UIWindow()
|
||||
notificationCenter.post(name: UIWindow.didBecomeKeyNotification,
|
||||
object: nil)
|
||||
}
|
||||
viewModel = nil
|
||||
|
||||
// Then
|
||||
wait(for: [expectation], timeout: 0.1)
|
||||
|
||||
@@ -78,31 +78,24 @@ open class GradientLoadingBarController {
|
||||
bindViewModelToView()
|
||||
}
|
||||
|
||||
/// By providing a custom deinitializer we make sure to remove the corresponding `gradientView` from its superview.
|
||||
deinit {
|
||||
if gradientView.superview != nil {
|
||||
gradientView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private methods
|
||||
|
||||
private func bindViewModelToView() {
|
||||
viewModel.superview.subscribeDistinct { [weak self] newSuperview, _ in
|
||||
self?.addGradientView(to: newSuperview)
|
||||
self?.updateSuperview(newSuperview)
|
||||
}.disposed(by: &disposeBag)
|
||||
}
|
||||
|
||||
private func addGradientView(to superview: UIView?) {
|
||||
guard let superview = superview else {
|
||||
// We've received an invalid superview.
|
||||
return
|
||||
private func updateSuperview(_ superview: UIView?) {
|
||||
// If the view’s superview is not nil, the superview releases the view.
|
||||
gradientView.removeFromSuperview()
|
||||
|
||||
if let superview = superview {
|
||||
gradientView.translatesAutoresizingMaskIntoConstraints = false
|
||||
superview.addSubview(gradientView)
|
||||
|
||||
setupConstraints(superview: superview)
|
||||
}
|
||||
|
||||
gradientView.translatesAutoresizingMaskIntoConstraints = false
|
||||
superview.addSubview(gradientView)
|
||||
|
||||
setupConstraints(superview: superview)
|
||||
}
|
||||
|
||||
// MARK: - Public methods
|
||||
|
||||
@@ -49,14 +49,16 @@ final class GradientLoadingBarViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
/// By providing a custom deinitializer we make sure to remove the corresponding `gradientView` from its superview.
|
||||
superviewSubject.value = nil
|
||||
}
|
||||
|
||||
// MARK: - Private methods
|
||||
|
||||
@objc private func didReceiveUIWindowDidBecomeKeyNotification(_: Notification) {
|
||||
guard let keyWindow = sharedApplication.keyWindow else { return }
|
||||
|
||||
// Prevent informing the listener multiple times.
|
||||
notificationCenter.removeObserver(self)
|
||||
|
||||
// Now that we have a valid key window, we can use it as superview.
|
||||
superviewSubject.value = keyWindow
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user