Skip to content

Commit 293327f

Browse files
Merge pull request #16 from callstack-internal/swift
feat: Swift support
2 parents dcba832 + 355807d commit 293327f

File tree

23 files changed

+1407
-388
lines changed

23 files changed

+1407
-388
lines changed

docs/OBJECTIVE_C.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ You can import it from:
124124

125125
**Constructors:**
126126

127-
`initWithModuleName andInitialProperties`
127+
`[ReactNativeViewController initWithModuleName:moduleName andInitialProperties:initialProps]`
128128

129129
| Param | Required | Type | Description |
130130
| ------------------ | --------- | ------------- | ------------------------------------------------------------- |

docs/SWIFT.md

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
## Swift
2+
3+
React Native Brownfield provides first-class support for Swift.
4+
5+
### `use_frameworks!` support
6+
7+
It is possible to build `react-native-brownfield` with `use_frameworks!` directive in CocoaPods as long as `React` can be built this way.
8+
9+
| React Native version | `use_frameworks!` compatibility |
10+
| -------------------------- | ------------------------------- |
11+
| <= 0.59.X | Compatible |
12+
| 0.60.X | Not compatible |
13+
| 0.61.0-rc.0 | Not compatible |
14+
15+
Please reffer to [this issue](https://github.com/facebook/react-native/issues/25349) to learn more about `use_frameworks!` state in React Native.
16+
17+
Until this behavior is fixed, you can access `react-native-brownfield` API in Swift via [Bridging Header](../example/swift/BridgingHeader.h).
18+
19+
### Linking
20+
21+
The library is meant to work with [auto linking](https://github.com/react-native-community/cli/blob/master/docs/autolinking.md). In case you can't use this feature, please check out the following options:
22+
23+
<details>
24+
<summary>react-native link</summary>
25+
Run the following command in your terminal:
26+
27+
```bash
28+
react-native link @react-native-community/slider
29+
```
30+
</details>
31+
32+
<details>
33+
<summary>CocoaPods</summary>
34+
Add the following line to your `Podfile`:
35+
36+
```ruby
37+
pod 'ReactNativeBrownfield', :path => '../node_modules/@callstack/react-native-brownfield/ios'
38+
```
39+
</details>
40+
41+
<details>
42+
<summary>Manually link the library on iOS</summary>
43+
44+
### `Open project.xcodeproj in Xcode`
45+
46+
Drag `ReactNativeBrownfield.xcodeproj` to your project on Xcode (usually under the Libraries group on Xcode):
47+
48+
![xcode-add](https://facebook.github.io/react-native/docs/assets/AddToLibraries.png)
49+
50+
### Link `libReactNativeBrownfield.a` binary with libraries
51+
52+
Click on your main project file (the one that represents the `.xcodeproj`) select `Build Phases` and drag the static library from the `Products` folder inside the Library you are importing to `Link Binary With Libraries` (or use the `+` sign and choose library from the list):
53+
54+
![xcode-link](https://facebook.github.io/react-native/docs/assets/AddToBuildPhases.png)
55+
</details>
56+
57+
### API Reference
58+
59+
#### ReactNativeBrownfield
60+
61+
You can import the object from:
62+
63+
```swift
64+
import ReactNativeBrownfield
65+
```
66+
67+
---
68+
69+
**Statics:**
70+
71+
`shared()`
72+
73+
A singleton that keeps an instance of ReactNativeBrownfield object.
74+
75+
Examples:
76+
77+
```swift
78+
ReactNativeBrownfield.shared()
79+
```
80+
81+
---
82+
83+
**Properties:**
84+
85+
| Property | Type | Default | Description |
86+
| -------------------- | --------- | -------------- | -------------------------------------------------- |
87+
| bridge | RCTBridge | nil | Launch options, typically passed from AppDelegate. |
88+
| entryFile | NSString | index | Path to JavaScript root. |
89+
| fallbackResource | NSString | nil | Path to bundle fallback resource. |
90+
| bundlePath | NSString | main.jsbundle | Path to bundle fallback resource. |
91+
92+
---
93+
94+
**Methods:**
95+
96+
`startReactNative`
97+
98+
Starts React Native, produces an instance of a bridge. You can use it to initialize React Native in your app.
99+
100+
Params:
101+
102+
| Param | Required | Type | Description |
103+
| ----------------------- | -------- | ------------- | ----------------------------------------------------- |
104+
| onBundleLoaded | No | () -> void | Callback invoked after JS bundle is fully loaded. |
105+
| launchOptions | No | NSDictionary | Launch options, typically passed from AppDelegate. |
106+
107+
Examples:
108+
109+
```swift
110+
ReactNativeBrownfield.shared().startReactNative()
111+
```
112+
113+
```swift
114+
ReactNativeBrownfield.shared().startReactNative {
115+
print("React Native started")
116+
}
117+
```
118+
119+
```swift
120+
ReactNativeBrownfield.shared().startReactNative({
121+
print("React Native started")
122+
}, launchOptions)
123+
```
124+
125+
---
126+
127+
#### ReactNativeViewController
128+
129+
A view controller that's rendering `RCTRootView` within its bounds. It automatically uses an instance of a bridge created in `startReactNative` method. It works well with exposed JavaScript module. It's the simplest way to embed React Native into your navigation stack.
130+
131+
You can import it from:
132+
133+
```swift
134+
import ReactNativeBrownfield
135+
```
136+
137+
---
138+
139+
**Constructors:**
140+
141+
`ReactNativeViewController(moduleName: moduleName, initialProperites:initialProperties)`
142+
143+
| Param | Required | Type | Description |
144+
| ------------------ | --------- | ------------- | ------------------------------------------------------------- |
145+
| moduleName | Yes | NSString | Name of React Native component registered to `AppRegistry`. |
146+
| initialProperties | No | NSString | Initial properties to be passed to React Native component. |
147+
148+
Examples:
149+
150+
```swift
151+
ReactNativeViewController(moduleName: "ReactNative")
152+
```
153+
154+
```swift
155+
ReactNativeViewController(moduleName: "ReactNative", initialProperites:["score": 12])
156+
```
157+
158+
---
159+
160+
### Linking
161+
162+
You can find an example app [here](../example/swift).
163+
164+

example/objc/NativeExample.xcodeproj/xcshareddata/xcschemes/NativeExample.xcscheme

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
shouldUseLaunchSchemeArgsEnv = "YES">
3030
<Testables>
3131
</Testables>
32+
<AdditionalOptions>
33+
</AdditionalOptions>
3234
</TestAction>
3335
<LaunchAction
3436
buildConfiguration = "Debug"
@@ -50,6 +52,8 @@
5052
ReferencedContainer = "container:NativeExample.xcodeproj">
5153
</BuildableReference>
5254
</BuildableProductRunnable>
55+
<AdditionalOptions>
56+
</AdditionalOptions>
5357
</LaunchAction>
5458
<ProfileAction
5559
buildConfiguration = "Release"

example/objc/Podfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ target 'NativeExample' do
55
pod 'React', :path => '../../node_modules/react-native/'
66
pod 'React-Core', :path => '../../node_modules/react-native/React'
77
pod 'React-DevSupport', :path => '../../node_modules/react-native/React'
8-
pod 'React-fishhook', :path => '../../node_modules/react-native/Libraries/fishhook'
98
pod 'React-RCTActionSheet', :path => '../../node_modules/react-native/Libraries/ActionSheetIOS'
109
pod 'React-RCTAnimation', :path => '../../node_modules/react-native/Libraries/NativeAnimation'
1110
pod 'React-RCTBlob', :path => '../../node_modules/react-native/Libraries/Blob'

example/swift/AppDelegate.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//
2+
// AppDelegate.swift
3+
// SwiftExample
4+
//
5+
// Created by Michal Chudziak on 25/08/2019.
6+
// Copyright © 2019 Callstack. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
@UIApplicationMain
12+
class AppDelegate: UIResponder, UIApplicationDelegate {
13+
14+
var window: UIWindow?
15+
16+
17+
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18+
// Override point for customization after application launch.
19+
ReactNativeBrownfield.shared().entryFile = "example/index"
20+
ReactNativeBrownfield.shared().startReactNative {
21+
print("loaded")
22+
}
23+
24+
return true
25+
}
26+
27+
func applicationWillResignActive(_ application: UIApplication) {
28+
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
29+
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
30+
}
31+
32+
func applicationDidEnterBackground(_ application: UIApplication) {
33+
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
34+
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
35+
}
36+
37+
func applicationWillEnterForeground(_ application: UIApplication) {
38+
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
39+
}
40+
41+
func applicationDidBecomeActive(_ application: UIApplication) {
42+
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43+
}
44+
45+
func applicationWillTerminate(_ application: UIApplication) {
46+
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
47+
}
48+
49+
50+
}
51+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "iphone",
5+
"size" : "20x20",
6+
"scale" : "2x"
7+
},
8+
{
9+
"idiom" : "iphone",
10+
"size" : "20x20",
11+
"scale" : "3x"
12+
},
13+
{
14+
"idiom" : "iphone",
15+
"size" : "29x29",
16+
"scale" : "2x"
17+
},
18+
{
19+
"idiom" : "iphone",
20+
"size" : "29x29",
21+
"scale" : "3x"
22+
},
23+
{
24+
"idiom" : "iphone",
25+
"size" : "40x40",
26+
"scale" : "2x"
27+
},
28+
{
29+
"idiom" : "iphone",
30+
"size" : "40x40",
31+
"scale" : "3x"
32+
},
33+
{
34+
"idiom" : "iphone",
35+
"size" : "60x60",
36+
"scale" : "2x"
37+
},
38+
{
39+
"idiom" : "iphone",
40+
"size" : "60x60",
41+
"scale" : "3x"
42+
},
43+
{
44+
"idiom" : "ipad",
45+
"size" : "20x20",
46+
"scale" : "1x"
47+
},
48+
{
49+
"idiom" : "ipad",
50+
"size" : "20x20",
51+
"scale" : "2x"
52+
},
53+
{
54+
"idiom" : "ipad",
55+
"size" : "29x29",
56+
"scale" : "1x"
57+
},
58+
{
59+
"idiom" : "ipad",
60+
"size" : "29x29",
61+
"scale" : "2x"
62+
},
63+
{
64+
"idiom" : "ipad",
65+
"size" : "40x40",
66+
"scale" : "1x"
67+
},
68+
{
69+
"idiom" : "ipad",
70+
"size" : "40x40",
71+
"scale" : "2x"
72+
},
73+
{
74+
"idiom" : "ipad",
75+
"size" : "76x76",
76+
"scale" : "1x"
77+
},
78+
{
79+
"idiom" : "ipad",
80+
"size" : "76x76",
81+
"scale" : "2x"
82+
},
83+
{
84+
"idiom" : "ipad",
85+
"size" : "83.5x83.5",
86+
"scale" : "2x"
87+
},
88+
{
89+
"idiom" : "ios-marketing",
90+
"size" : "1024x1024",
91+
"scale" : "1x"
92+
}
93+
],
94+
"info" : {
95+
"version" : 1,
96+
"author" : "xcode"
97+
}
98+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"version" : 1,
4+
"author" : "xcode"
5+
}
6+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
3+
<dependencies>
4+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
5+
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
6+
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
7+
</dependencies>
8+
<scenes>
9+
<!--View Controller-->
10+
<scene sceneID="EHf-IW-A2E">
11+
<objects>
12+
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
13+
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
14+
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
15+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
16+
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
17+
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
18+
</view>
19+
</viewController>
20+
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
21+
</objects>
22+
<point key="canvasLocation" x="53" y="375"/>
23+
</scene>
24+
</scenes>
25+
</document>

0 commit comments

Comments
 (0)