Skip to content

Commit a29deb8

Browse files
committed
feat: support packaging as a framework
1 parent 2c12594 commit a29deb8

File tree

10 files changed

+132
-65
lines changed

10 files changed

+132
-65
lines changed

ReactBrownfield.podspec

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,13 @@ Pod::Spec.new do |spec|
1515
spec.module_name = "ReactBrownfield"
1616
spec.source = { :git => "git@github.com:callstack/react-native-brownfield.git", :tag => "#{spec.version}" }
1717
spec.source_files = "ios/**/*.{h,m,mm,swift}"
18-
spec.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
18+
spec.pod_target_xcconfig = {
19+
'DEFINES_MODULE' => 'YES',
20+
'OTHER_SWIFT_FLAGS' => "-enable-experimental-feature AccessLevelOnImport"
21+
}
1922

2023
spec.dependency 'ReactAppDependencyProvider'
24+
add_dependency(spec, "React-RCTAppDelegate")
25+
2126
install_modules_dependencies(spec)
2227
end

docs/OBJECTIVE_C.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ Examples:
3535
| `entryFile` | `NSString` | `index` | Path to JavaScript root. |
3636
| `fallbackResource` | `NSString` | `nil` | Path to bundle fallback resource. |
3737
| `bundlePath` | `NSString` | `main.jsbundle`| Path to bundle fallback resource. |
38-
| `reactNativeFactory` | `RCTReactNativeFactory` | `nil` | React Native factory instance. |
3938

4039
---
4140

@@ -70,6 +69,24 @@ Examples:
7069
}, launchOptions];
7170
```
7271

72+
`view`
73+
74+
Creates a React Native view for the specified module name.
75+
76+
Params:
77+
78+
| Param | Required | Type | Description |
79+
| ----------------------- | -------- | ----------------- | ----------------------------------------------------- |
80+
| `moduleName` | Yes | `NSString` | Name of React Native component registered to `AppRegistry`. |
81+
| `initialProps` | No | `NSDictionary` | Initial properties to be passed to React Native component. |
82+
| `launchOptions` | No | `NSDictionary` | Launch options, typically passed from AppDelegate. |
83+
84+
Examples:
85+
86+
```objc
87+
UIView *view = [[ReactNativeBrownfield shared] viewWithModuleName:@"ReactNative" initialProps:@{@"score": @12}];
88+
```
89+
7390
---
7491
7592
#### `ReactNativeViewController`

docs/SWIFT.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ ReactNativeBrownfield.shared
3535
| `entryFile` | `String` | index | Path to JavaScript root. |
3636
| `fallbackResource` | `String?` | nil | Path to bundle fallback resource. |
3737
| `bundlePath` | `String` | main.jsbundle | Path to bundle fallback resource. |
38-
| `reactNativeFactory` | `RCTReactNativeFactory?` | nil | React Native factory instance. |
3938

4039
---
4140

4241
**Methods:**
4342

43+
4444
`startReactNative`
4545

4646
Starts React Native. You can use it to initialize React Native in your app.
@@ -70,6 +70,27 @@ ReactNativeBrownfield.shared.startReactNative(onBundleLoaded: {
7070
}, launchOptions: launchOptions)
7171
```
7272

73+
`view`
74+
75+
Creates a React Native view for the specified module name.
76+
77+
Params:
78+
79+
| Param | Required | Type | Description |
80+
| ----------------------- | -------- | ------------------- | ----------------------------------------------------- |
81+
| `moduleName` | Yes | `String` | Name of React Native component registered to `AppRegistry`. |
82+
| `initialProps` | No | `[AnyHashable: Any]?` | Initial properties to be passed to React Native component. |
83+
| `launchOptions` | No | `[AnyHashable: Any]?` | Launch options, typically passed from AppDelegate. |
84+
85+
Examples:
86+
87+
```swift
88+
let view = ReactNativeBrownfield.shared.view(
89+
moduleName: "ReactNative",
90+
initialProps: ["score": 12]
91+
)
92+
```
93+
7394
---
7495

7596
#### Initialization Approaches
@@ -238,5 +259,3 @@ NavigationLink("Open React Native Screen") {
238259
### Example
239260

240261
You can find an example app [here](../example/swift).
241-
242-

example/swift/Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ target 'SwiftExample' do
2828
installer,
2929
config[:reactNativePath],
3030
:mac_catalyst_enabled => false,
31-
:ccache_enabled => true
31+
# :ccache_enabled => true
3232
)
3333
end
3434
end

example/swift/Podfile.lock

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ PODS:
15271527
- React-jsi (= 0.78.0)
15281528
- ReactAppDependencyProvider (0.78.0):
15291529
- ReactCodegen
1530-
- ReactBrownfield (1.0.0-rc.0):
1530+
- ReactBrownfield (1.0.0-rc.1):
15311531
- DoubleConversion
15321532
- glog
15331533
- hermes-engine
@@ -1541,6 +1541,7 @@ PODS:
15411541
- React-graphics
15421542
- React-ImageManager
15431543
- React-NativeModulesApple
1544+
- React-RCTAppDelegate
15441545
- React-RCTFabric
15451546
- React-rendererdebug
15461547
- React-utils
@@ -1944,13 +1945,13 @@ SPEC CHECKSUMS:
19441945
React-timing: bb220a53a795ed57976a4855c521f3de2f298fe5
19451946
React-utils: 3b054aaebe658fc710a8d239d0e4b9fd3e0b78f9
19461947
ReactAppDependencyProvider: a1fb08dfdc7ebc387b2e54cfc9decd283ed821d8
1947-
ReactBrownfield: e05f198df083698ed9942ace80fd90da6e9298de
1948+
ReactBrownfield: f2e119f0241af9303f55556a63385efc58ce49b7
19481949
ReactCodegen: 008c319179d681a6a00966edfc67fda68f9fbb2e
19491950
ReactCommon: 0c097b53f03d6bf166edbcd0915da32f3015dd90
19501951
RNScreens: 0d4cb9afe052607ad0aa71f645a88bb7c7f2e64c
19511952
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
19521953
Yoga: afd04ff05ebe0121a00c468a8a3c8080221cb14c
19531954

1954-
PODFILE CHECKSUM: b5dc5f822e98018cbffd7384516e146bba9f6d99
1955+
PODFILE CHECKSUM: dd9bed4f3821ab08d739dbded562f749348cd4d7
19551956

19561957
COCOAPODS: 1.15.2

example/swift/SwiftExample.xcodeproj/project.pbxproj

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,10 @@
328328
ONLY_ACTIVE_ARCH = YES;
329329
OTHER_CFLAGS = "$(inherited)";
330330
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
331-
OTHER_LDFLAGS = "$(inherited) ";
331+
OTHER_LDFLAGS = (
332+
"$(inherited)",
333+
" ",
334+
);
332335
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
333336
SDKROOT = iphoneos;
334337
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
@@ -392,7 +395,10 @@
392395
MTL_FAST_MATH = YES;
393396
OTHER_CFLAGS = "$(inherited)";
394397
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
395-
OTHER_LDFLAGS = "$(inherited) ";
398+
OTHER_LDFLAGS = (
399+
"$(inherited)",
400+
" ",
401+
);
396402
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
397403
SDKROOT = iphoneos;
398404
SWIFT_COMPILATION_MODE = wholemodule;

ios/ReactNativeBrownfield.swift

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,44 @@
1-
import React
2-
import React_RCTAppDelegate
3-
import ReactAppDependencyProvider
1+
import UIKit
2+
internal import React
3+
internal import React_RCTAppDelegate
4+
internal import ReactAppDependencyProvider
45

5-
@objc public class ReactNativeBrownfield: RCTDefaultReactNativeFactoryDelegate {
6-
@objc public static let shared = ReactNativeBrownfield()
7-
private var onBundleLoaded: (() -> Void)?
6+
class ReactNativeBrownfieldDelegate: RCTDefaultReactNativeFactoryDelegate {
7+
var entryFile = "index"
8+
// MARK: - RCTReactNativeFactoryDelegate Methods
9+
10+
override func sourceURL(for bridge: RCTBridge) -> URL? {
11+
return bundleURL()
12+
}
13+
14+
public override func bundleURL() -> URL? {
15+
#if DEBUG
16+
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: entryFile)
17+
#else
18+
let resourceURLComponents = bundlePath.components(separatedBy: ".")
19+
let withoutLast = resourceURLComponents[..<(resourceURLComponents.count - 1)]
20+
let resourceName = withoutLast.joined()
21+
let fileExtension = resourceURLComponents.last ?? ""
22+
23+
return Bundle.main.url(forResource: resourceName, withExtension: fileExtension)
24+
#endif
25+
}
26+
}
827

28+
@objc public class ReactNativeBrownfield: NSObject {
29+
public static let shared = ReactNativeBrownfield()
30+
private var onBundleLoaded: (() -> Void)?
31+
private var delegate = ReactNativeBrownfieldDelegate()
32+
933
/**
1034
* Path to JavaScript root.
1135
* Default value: "index"
1236
*/
13-
@objc public var entryFile: String = "index"
37+
@objc public var entryFile: String = "index" {
38+
didSet {
39+
delegate.entryFile = entryFile
40+
}
41+
}
1442
/**
1543
* Path to bundle fallback resource.
1644
* Default value: nil
@@ -25,24 +53,36 @@ import ReactAppDependencyProvider
2553
* React Native factory instance created when starting React Native.
2654
* Default value: nil
2755
*/
28-
@objc public var reactNativeFactory: RCTReactNativeFactory? = nil
56+
private var reactNativeFactory: RCTReactNativeFactory? = nil
2957
/**
3058
* Root view factory used to create React Native views.
3159
*/
32-
@objc lazy public var rootViewFactory: RCTRootViewFactory? = {
60+
lazy private var rootViewFactory: RCTRootViewFactory? = {
3361
return reactNativeFactory?.rootViewFactory
3462
}()
35-
63+
3664
/**
3765
* Starts React Native with default parameters.
3866
*/
3967
@objc public func startReactNative() {
4068
startReactNative(onBundleLoaded: nil)
4169
}
4270

71+
@objc public func view(
72+
moduleName: String,
73+
initialProps: [AnyHashable: Any]?,
74+
launchOptions: [AnyHashable: Any]? = nil
75+
) -> UIView? {
76+
reactNativeFactory?.rootViewFactory.view(
77+
withModuleName: moduleName,
78+
initialProperties: initialProps,
79+
launchOptions: launchOptions
80+
)
81+
}
82+
4383
/**
4484
* Starts React Native with optional callback when bundle is loaded.
45-
*
85+
*
4686
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
4787
*/
4888
@objc public func startReactNative(onBundleLoaded: (() -> Void)?) {
@@ -51,15 +91,15 @@ import ReactAppDependencyProvider
5191

5292
/**
5393
* Starts React Native with optional callback and launch options.
54-
*
94+
*
5595
* @param onBundleLoaded Optional callback invoked after JS bundle is fully loaded.
5696
* @param launchOptions Launch options, typically passed from AppDelegate.
5797
*/
5898
@objc public func startReactNative(onBundleLoaded: (() -> Void)?, launchOptions: [AnyHashable: Any]?) {
5999
guard reactNativeFactory == nil else { return }
60100

61-
self.dependencyProvider = RCTAppDependencyProvider()
62-
self.reactNativeFactory = RCTReactNativeFactory(delegate: self)
101+
delegate.dependencyProvider = RCTAppDependencyProvider()
102+
self.reactNativeFactory = RCTReactNativeFactory(delegate: delegate)
63103

64104
if let onBundleLoaded {
65105
self.onBundleLoaded = onBundleLoaded
@@ -86,25 +126,6 @@ import ReactAppDependencyProvider
86126
onBundleLoaded = nil
87127
NotificationCenter.default.removeObserver(self)
88128
}
89-
90-
// MARK: - RCTReactNativeFactoryDelegate Methods
91-
92-
@objc public override func sourceURL(for bridge: RCTBridge) -> URL? {
93-
return bundleURL()
94-
}
95-
96-
public override func bundleURL() -> URL? {
97-
#if DEBUG
98-
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: entryFile)
99-
#else
100-
let resourceURLComponents = bundlePath.components(separatedBy: ".")
101-
let withoutLast = resourceURLComponents[..<(resourceURLComponents.count - 1)]
102-
let resourceName = withoutLast.joined()
103-
let fileExtension = resourceURLComponents.last ?? ""
104-
105-
return Bundle.main.url(forResource: resourceName, withExtension: fileExtension)
106-
#endif
107-
}
108129
}
109130

110131
extension Notification.Name {

ios/ReactNativeBrownfieldModule.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#ifdef __cplusplus
22

3-
#import <React-RCTAppDelegate/RCTDefaultReactNativeFactoryDelegate.h>
43
#import <ReactNativeBrownfield/ReactNativeBrownfield.h>
54

65
@interface ReactNativeBrownfieldModule : NSObject <NativeReactNativeBrownfieldModuleSpec>

ios/ReactNativeBrownfieldModule.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React
1+
internal import React
22

33
@objcMembers
44
public class ReactNativeBrownfieldModuleImpl: NSObject {
@@ -8,7 +8,7 @@ public class ReactNativeBrownfieldModuleImpl: NSObject {
88
NotificationCenter.default.post(name: Notification.Name.togglePopGestureRecognizer, object: nil, userInfo: userInfo)
99
}
1010
}
11-
11+
1212
static public func popToNative(animated: Bool) {
1313
let userInfo = ["animated": animated]
1414
DispatchQueue.main.async {

0 commit comments

Comments
 (0)