Skip to content

Commit f51f6f9

Browse files
authored
Presentable allowStepWhenDismissed is ignored and overridden with parent flow (#196)
Co-authored-by: Mikhail Markin <[email protected]> Thanks for your contribution!
1 parent 367eb93 commit f51f6f9

File tree

3 files changed

+65
-6
lines changed

3 files changed

+65
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
** *Unreleased* **:
2+
- fix: presentable `allowStepWhenDismissed` now are not ignored and not overridden by parent flow
23
- fix: `displayed` and `rxVisible` now do not assume UIViewController starts not visible
34

45
** Version 2.13.0 **:

RxFlow/FlowCoordinator.swift

+7-6
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public final class FlowCoordinator: NSObject {
9797
// the FlowContributor is not related to a new Flow but to a Presentable/Stepper
9898
// this new Stepper will contribute to the current Flow.
9999
.flatMap { [weak self] in
100-
self?.steps(from: $0, within: flow, allowStepWhenDismissed: allowStepWhenDismissed) ?? Signal.empty()
100+
self?.steps(from: $0) ?? Signal.empty()
101101
}
102102
.asObservable()
103103
.take(until: allowStepWhenDismissed ? .empty() : flow.rxDismissed.asObservable())
@@ -172,18 +172,19 @@ public final class FlowCoordinator: NSObject {
172172
/// retrieve Steps from the combination presentable/stepper
173173
///
174174
/// - Parameter nextPresentableAndStepper: the combination presentable/stepper that will generate new Steps
175-
/// - Parameter flow: the Flow in which the stepper emits new steps
176175
/// - Returns: the reactive sequence of Steps from the combination presentable/stepper
177-
private func steps (from nextPresentableAndStepper: PresentableAndStepper,
178-
within flow: Flow,
179-
allowStepWhenDismissed: Bool = false) -> Signal<Step> {
176+
private func steps(from nextPresentableAndStepper: PresentableAndStepper) -> Signal<Step> {
180177
var stepStream = nextPresentableAndStepper
181178
.stepper
182179
.steps
183180
.do(onSubscribed: { nextPresentableAndStepper.stepper.readyToEmitSteps() })
184181
.startWith(nextPresentableAndStepper.stepper.initialStep)
185182
.filter { !($0 is NoneStep) }
186-
.take(until: allowStepWhenDismissed ? .empty() : nextPresentableAndStepper.presentable.rxDismissed.asObservable())
183+
.take(
184+
until: nextPresentableAndStepper.allowStepWhenDismissed
185+
? .empty()
186+
: nextPresentableAndStepper.presentable.rxDismissed.asObservable()
187+
)
187188

188189
// by default we cannot accept steps from a presentable that is not visible
189190
if nextPresentableAndStepper.allowStepWhenNotPresented == false {

RxFlowTests/FlowCoordinatorTests.swift

+57
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,36 @@ final class TestLeakingFlow: Flow {
230230
}
231231
}
232232

233+
final class TestChildLeakingFlow: Flow {
234+
final class ChildViewController: UIViewController {
235+
var onDeinit: (() -> Void)? = nil
236+
237+
deinit {
238+
onDeinit?()
239+
}
240+
}
241+
242+
var root: Presentable = UIViewController()
243+
weak var childViewController: ChildViewController? = nil
244+
245+
func navigate(to step: Step) -> FlowContributors {
246+
guard let step = step as? TestSteps else { return .none }
247+
248+
switch step {
249+
case .one:
250+
let viewController = ChildViewController()
251+
childViewController = viewController
252+
let flowContributor = FlowContributor.contribute(
253+
withNextPresentable: viewController,
254+
withNextStepper: DefaultStepper()
255+
)
256+
return .one(flowContributor: flowContributor)
257+
default:
258+
return .none
259+
}
260+
}
261+
}
262+
233263
final class FlowCoordinatorTests: XCTestCase {
234264

235265
func testCoordinateWithOneStepper() {
@@ -368,6 +398,33 @@ final class FlowCoordinatorTests: XCTestCase {
368398

369399
XCTAssertNil(leakingFlowReference)
370400
}
401+
402+
func testChildViewControllerIsNotLeakingWhenParentFlowAllowsStepWhenDismissed() throws {
403+
let exp = expectation(description: "Flow when ready")
404+
let flowCoordinator = FlowCoordinator()
405+
let parentFlow = TestChildLeakingFlow()
406+
407+
flowCoordinator.coordinate(flow: parentFlow,
408+
with: OneStepper(withSingleStep: TestSteps.one),
409+
allowStepWhenDismissed: true)
410+
411+
Flows.use(parentFlow, when: .created) { (_) in
412+
exp.fulfill()
413+
}
414+
415+
waitForExpectations(timeout: 1)
416+
417+
XCTAssertNotNil(parentFlow.childViewController)
418+
419+
let deallocExp = expectation(description: "Child view controller deallocated")
420+
parentFlow.childViewController?.onDeinit = { deallocExp.fulfill() }
421+
422+
try XCTUnwrap(parentFlow.childViewController).didMove(toParent: nil)
423+
424+
waitForExpectations(timeout: 1)
425+
426+
XCTAssertNil(parentFlow.childViewController)
427+
}
371428

372429
func testNavigate_executes_on_mainThread() {
373430
class ThreadRecorderFlow: Flow {

0 commit comments

Comments
 (0)