现有项目集成react-native

原项目地址

1. 配置目录结构

创建新文件夹比如 2048-rn-app ,在该文件夹下面

1
mkdir ios

将原有项目移到ios文件夹下

2. 安装Javascript依赖

2048-rn-app 下创建 _package.json_,并写入以下内容(可自行更改参数)

1
2
3
4
5
6
7
8
{
"name": "2048",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
}
}

安装react和react native:在命令行运行

1
yarn add react react-native

3.安装CocoaPods

1
brew install cocoapods

4.将React Native导入到项目

1
2
cd ios
pod init

根据需求导入需要的库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'

target 'NumberTileGame' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!

# Pods for NumberTileGame
# Your 'node_modules' directory is probably in the root of your project,
# but if not, adjust the `:path` accordingly
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'DevSupport', # Include this to enable In-App Devmenu if RN >= 0.43
'RCTText',
'RCTImage',
'RCTNetwork',
'RCTWebSocket', # needed for debugging
'BatchedBridge',
# Add any other subspecs you want to use in your project
]
# Explicitly include Yoga if you are using RN >= 0.42.0
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

# Third party deps podspec link
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'GLog', :podspec => '../node_modules/react-native/third-party-podspecs/GLog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

target 'NumberTileGameTests' do
inherit! :search_paths
# Pods for testing
end

end

安装依赖

1
pod install

5.开始RN开发

  • 创建 index.js

  • 添加代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    import React from 'react';
    import {AppRegistry, StyleSheet, Text, View} from 'react-native';

    class RNHighScores extends React.Component {
    render() {
    var contents = this.props['scores'].map(score => (
    <Text key={score.name}>
    {score.name}:{score.value}
    {'\n'}
    </Text>
    ));
    return (
    <View style={styles.container}>
    <Text style={styles.highScoresTitle}>2048 High Scores!</Text>
    <Text style={styles.scores}>{contents}</Text>
    </View>
    );
    }
    }

    const styles = StyleSheet.create({
    container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#FFFFFF',
    },
    highScoresTitle: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
    },
    scores: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
    },
    });

    // Module name
    AppRegistry.registerComponent('RNHighScores', () => RNHighScores);
  • 在ios工程中添加代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # AppDelegate.h
    #import <React/RCTBridgeDelegate.h>
    #import <React/RCTBridge.h>

    @interface F3HAppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>

    @property (strong, nonatomic) UIWindow *window;
    @property (strong, nonatomic) RCTBridge *rnBridge;


    @end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# AppDelegate.m

#import <React/RCTBundleURLProvider.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.rnBridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
return YES;
}

#pragma mark - RCTBridgeDelegate
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
NSURL *jsCodeLocation;

jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
return jsCodeLocation;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# F3HViewController.m

#import <React/RCTRootView.h>
#import <React/RCTBridge.h>

- (IBAction)goToHighScores:(UIButton *)sender {
NSLog(@"High Score Button Pressed");
// NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
// [[RCTRootView alloc] initWithBundleURL: jsCodeLocation
// moduleName: @"RNHighScores"
// initialProperties:nil
// launchOptions: nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:_rnBridge
moduleName:@"RNHighScores"
initialProperties:@{
@"scores" : @[
@{
@"name" : @"Alex",
@"value": @"42"
},
@{
@"name" : @"Joel",
@"value": @"10"
}
]
}
];
UIViewController *vc = [[UIViewController alloc] init];
vc.view = rootView;
[self.navigationController pushViewController:vc animated:YES];
}

- (IBAction)goToAbout:(UIButton *)sender {
NSLog(@"About Button Pressed");
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:_rnBridge
moduleName:@"About"
initialProperties:nil
];
UIViewController *vc = [[UIViewController alloc] init];
vc.view = rootView;
[self.navigationController pushViewController:vc animated:YES];
}

image

image

image

优化建议

Note that RCTRootView initWithURL starts up a new JSC VM. To save resources and simplify the communication between RN views in different parts of your native app, you can have multiple views powered by React Native that are associated with a single JS runtime. To do that, instead of using [RCTRootView alloc] initWithURL, use RCTBridge initWithBundleURL to create a bridge and then use RCTRootView initWithBridge.

自动生成main.jsbundle

1
2
export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh

项目地址
参考链接