Skip to content

Commit ef13353

Browse files
author
Nazar Sydiaha
committed
feat: add stopReactNative method
1 parent d10a0d8 commit ef13353

File tree

3 files changed

+55
-7
lines changed

3 files changed

+55
-7
lines changed

docs/OBJECTIVE_C.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@ Examples:
7070
}, launchOptions];
7171
```
7272

73+
`stopReactNative`
74+
75+
Stops React Native and releases the underlying runtime. Safe to call multiple times. Call it after all React Native views are dismissed.
76+
77+
Examples:
78+
79+
```objc
80+
[[ReactNativeBrownfield shared] stopReactNative];
81+
```
82+
7383
`view`
7484

7585
Creates a React Native view for the specified module name.

docs/SWIFT.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@ ReactNativeBrownfield.shared.startReactNative(onBundleLoaded: {
7070
}, launchOptions: launchOptions)
7171
```
7272

73+
`stopReactNative`
74+
75+
Stops React Native and releases the underlying runtime. Safe to call multiple times. Call it after all React Native views are dismissed.
76+
77+
Examples:
78+
79+
```swift
80+
ReactNativeBrownfield.shared.stopReactNative()
81+
```
82+
7383
`view`
7484

7585
Creates a React Native view for the specified module name.

ios/ReactNativeBrownfield.swift

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ class ReactNativeBrownfieldDelegate: RCTDefaultReactNativeFactoryDelegate {
3232
private var onBundleLoaded: (() -> Void)?
3333
private var delegate = ReactNativeBrownfieldDelegate()
3434

35+
private func checkFactoryInitialized(launchOptions: [AnyHashable: Any]? = nil) {
36+
if reactNativeFactory == nil {
37+
delegate.dependencyProvider = RCTAppDependencyProvider()
38+
self.reactNativeFactory = RCTReactNativeFactory(delegate: delegate)
39+
}
40+
}
41+
3542
/**
3643
* Path to JavaScript root.
3744
* Default value: "index"
@@ -71,10 +78,12 @@ class ReactNativeBrownfieldDelegate: RCTDefaultReactNativeFactoryDelegate {
7178
private var reactNativeFactory: RCTReactNativeFactory? = nil
7279
/**
7380
* Root view factory used to create React Native views.
81+
* Always proxies the currently active React Native factory so restarting
82+
* React Native yields a fresh root view factory instance.
7483
*/
75-
lazy private var rootViewFactory: RCTRootViewFactory? = {
76-
return reactNativeFactory?.rootViewFactory
77-
}()
84+
private var rootViewFactory: RCTRootViewFactory? {
85+
reactNativeFactory?.rootViewFactory
86+
}
7887

7988
/**
8089
* Starts React Native with default parameters.
@@ -88,7 +97,9 @@ class ReactNativeBrownfieldDelegate: RCTDefaultReactNativeFactoryDelegate {
8897
initialProps: [AnyHashable: Any]?,
8998
launchOptions: [AnyHashable: Any]? = nil
9099
) -> UIView? {
91-
rootViewFactory?.view(
100+
checkFactoryInitialized(launchOptions: launchOptions)
101+
102+
return rootViewFactory?.view(
92103
withModuleName: moduleName,
93104
initialProperties: initialProps,
94105
launchOptions: launchOptions
@@ -112,9 +123,7 @@ class ReactNativeBrownfieldDelegate: RCTDefaultReactNativeFactoryDelegate {
112123
*/
113124
@objc public func startReactNative(onBundleLoaded: (() -> Void)?, launchOptions: [AnyHashable: Any]?) {
114125
guard reactNativeFactory == nil else { return }
115-
116-
delegate.dependencyProvider = RCTAppDependencyProvider()
117-
self.reactNativeFactory = RCTReactNativeFactory(delegate: delegate)
126+
checkFactoryInitialized(launchOptions: launchOptions)
118127

119128
if let onBundleLoaded {
120129
self.onBundleLoaded = onBundleLoaded
@@ -136,6 +145,25 @@ class ReactNativeBrownfieldDelegate: RCTDefaultReactNativeFactoryDelegate {
136145
}
137146
}
138147

148+
/**
149+
* Stops React Native and releases the underlying factory instance.
150+
*/
151+
@objc public func stopReactNative() {
152+
if !Thread.isMainThread {
153+
DispatchQueue.main.async { [weak self] in self?.stopReactNative() }
154+
return
155+
}
156+
157+
guard let factory = reactNativeFactory else { return }
158+
159+
factory.bridge?.invalidate()
160+
161+
NotificationCenter.default.removeObserver(self)
162+
onBundleLoaded = nil
163+
164+
reactNativeFactory = nil
165+
}
166+
139167
@objc private func jsLoaded(_ notification: Notification) {
140168
onBundleLoaded?()
141169
onBundleLoaded = nil

0 commit comments

Comments
 (0)