From 2cba1e09eb439c9b79ccbf1aa07881b63d53f255 Mon Sep 17 00:00:00 2001 From: Mike Gray Date: Wed, 6 Sep 2023 15:18:59 -0400 Subject: [PATCH] Fix `displayed` to not assume UIViewController starts not displayed (#192) * Fix `displayed` to not assume UIViewController starts not displayed * Update changelog --- CHANGELOG.md | 3 +++ .../Reactive+UIViewController.swift | 5 ++-- .../UIViewController+PresentableTests.swift | 24 +++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91c836b..a06bcc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +** *Unreleased* **: +- fix: `displayed` and `rxVisible` now do not assume UIViewController starts not visible + ** Version 2.13.0 **: - fix: use xcframeworks for RxFlow/RxFlowDemo deps to please Carthage diff --git a/RxFlow/Extensions/Reactive+UIViewController.swift b/RxFlow/Extensions/Reactive+UIViewController.swift index 1e2ac70..5b19268 100644 --- a/RxFlow/Extensions/Reactive+UIViewController.swift +++ b/RxFlow/Extensions/Reactive+UIViewController.swift @@ -31,8 +31,9 @@ public extension Reactive where Base: UIViewController { var displayed: Observable { let viewDidAppearObservable = self.sentMessage(#selector(Base.viewDidAppear)).map { _ in true } let viewDidDisappearObservable = self.sentMessage(#selector(Base.viewDidDisappear)).map { _ in false } - // a UIViewController is at first not displayed - let initialState = Observable.just(false) + let initialState = Observable.deferred { + .just(base.viewIfLoaded?.window != nil) + } // future calls to viewDidAppear and viewDidDisappear will change the displayable state return initialState.concat(Observable.merge(viewDidAppearObservable, viewDidDisappearObservable)) } diff --git a/RxFlowTests/UIViewController+PresentableTests.swift b/RxFlowTests/UIViewController+PresentableTests.swift index 09fe617..24ce6af 100644 --- a/RxFlowTests/UIViewController+PresentableTests.swift +++ b/RxFlowTests/UIViewController+PresentableTests.swift @@ -42,6 +42,30 @@ final class UIViewController_PresentableTests: XCTestCase { } } + func testUIViewControllerVisibleStartsVisible() { + // Given: a UIViewController that starts "displayed" + let window = UIWindow() + let viewController = TestUIViewController() + _ = viewController.view + window.rootViewController = viewController + window.makeKeyAndVisible() + let testScheduler = TestScheduler(initialClock: 0) + let observer = testScheduler.createObserver(Bool.self) + testScheduler.start() + + // When: subscribing to rxVisible + _ = viewController.rxVisible.asObservable().take(until: self.rx.deallocating).bind(to: observer) + + // Then: rxVisible emits the first value as true + let referenceVisible = [true] + XCTAssertEqual(observer.events.count, 1) + var index = 0 + referenceVisible.forEach { + XCTAssertEqual(observer.events[index].value.element, $0) + index += 1 + } + } + func testUIViewControllerDismissed() { // Given: a UIViewController let viewController = TestUIViewController()