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()