Skip to content

Commit 5450937

Browse files
authored
Add scopeWillDeinit lifecycle method to PluginizedComponent (#444)
1 parent e2ad104 commit 5450937

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

Sources/NeedleFoundation/Pluginized/PluginizedComponent.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ open class PluginizedComponent<DependencyType, PluginExtensionType, NonCoreCompo
146146
case .inactive:
147147
self.releasableNonCoreComponent?.scopeDidBecomeInactive()
148148
case .deinit:
149+
self.scopeWillDeinit()
150+
149151
// Only release the non-core component after the consumer, which should
150152
// be the owner reference to the component is released. Cannot release
151153
// the non-core component when the bound lifecyle is deactivated. The
@@ -156,6 +158,12 @@ open class PluginizedComponent<DependencyType, PluginExtensionType, NonCoreCompo
156158
}
157159
}
158160
}
161+
162+
/// Indicates that the corresponding scope will deinit
163+
///
164+
/// - note: This method is automatically invoked when the bound `PluginizedScopeLifecycleObservable`
165+
/// enters its `deinit` state
166+
open func scopeWillDeinit() {}
159167

160168
// MARK: - Private
161169

Tests/NeedleFoundationTests/Pluginized/PluginizedComponentTests.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,27 @@ class PluginizedComponentTests: XCTestCase {
9494
XCTAssertNil(noncoreComponent)
9595
XCTAssertEqual(noncoreDeinitCallCount, 1)
9696
}
97+
98+
func test_bindTo_verifyWillDeinit() {
99+
let mockPluginizedComponent = MockPluginizedComponent()
100+
let mockDisposable = MockObserverDisposable()
101+
let mockLifecycle = MockPluginizedScopeLifecycleObervable(disposable: mockDisposable)
102+
mockPluginizedComponent.bind(to: mockLifecycle)
103+
104+
XCTAssertEqual(mockPluginizedComponent.scopeWillDeinitCallCount, 0)
105+
106+
mockLifecycle.observer!(.active)
107+
108+
XCTAssertEqual(mockPluginizedComponent.scopeWillDeinitCallCount, 0)
109+
110+
mockLifecycle.observer!(.inactive)
111+
112+
XCTAssertEqual(mockPluginizedComponent.scopeWillDeinitCallCount, 0)
113+
114+
mockLifecycle.observer!(.deinit)
115+
116+
XCTAssertEqual(mockPluginizedComponent.scopeWillDeinitCallCount, 1)
117+
}
97118
}
98119

99120
class MockNonCoreComponent: NonCoreComponent<EmptyDependency> {
@@ -122,9 +143,15 @@ class EmptyPluginExtensionsProvider: EmptyPluginExtensions {}
122143

123144
class MockPluginizedComponent: PluginizedComponent<EmptyDependency, EmptyPluginExtensions, MockNonCoreComponent> {
124145

146+
var scopeWillDeinitCallCount = 0
147+
125148
init() {
126149
super.init(parent: BootstrapComponent())
127150
}
151+
152+
override func scopeWillDeinit() {
153+
scopeWillDeinitCallCount += 1
154+
}
128155
}
129156

130157
class MockPluginizedScopeLifecycleObervable: PluginizedScopeLifecycleObservable {

0 commit comments

Comments
 (0)