I just make whole process with start from clean Xcode project. Usually I simple create RN application, eject and then translate to cocoapods ios part.
It largely based on RN docs: http://facebook.github.io/react-native/docs/0.51/integration-with-existing-apps.html
So environment: macOS Sierra, Xcode 9.2, RN 0.51.0
Project name: MyApp
Prepare
- Create new Xcode project, from 'Single View App' template, product name "MyApp", language Objective-C
- Run, see it works
cd MyApp
, mkdir ios
, mv MyApp* ios
(move all ios related files to ios subfolder)
Install npm dependencies
Create package.json
in root folder of you project (very basic)
{
"name": "MyApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "16.0.0",
"react-native": "0.51.0"
},
"devDependencies": {
"babel-jest": "22.0.4",
"babel-preset-react-native": "4.0.0"
}
}
Run npm install
Seup cocoapods
cd ios
pod init
(generate Podfile)
- declare react dependencies in Podfile in MyApp target
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'CxxBridge',
'RCTAnimation',
'RCTBlob',
'RCTText',
'RCTNetwork',
'RCTWebSocket',
'RCTImage',
'RCTLinkingIOS',
'DevSupport',
]
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
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'
You can add/remove React subspecs to include/remove RN functionality, this is hard process because RN components not fully independant.
pod install
(integrate pods into project, will create MyApp.xcworkspace, it should be used to compile application)
open MyApp.xcworkspace
, build & run, app should still work
Embed RN Root View
Replace you AppDelegate.m with this snippet:
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#if RCT_DEV
#import <React/RCTDevLoadingView.h>
#endif
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
RCTBundleURLProvider* provider = [RCTBundleURLProvider sharedSettings];
NSURL* jsCodeLocation = [provider jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:jsCodeLocation moduleProvider:nil launchOptions:launchOptions];
#if RCT_DEV
[bridge moduleForClass:[RCTDevLoadingView class]];
#endif
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"MyApp" initialProperties:@{}];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
@end
- Add ATS exception to Info.plist (or MyApp will be unable to connect to packager server with http)
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
- Compile & run in Simulator, you should see red screen with message "No bundle URL present." (it is because no packager server running & no compiled jsbundle exists)
Javascript part
Create MyApp/index.js
with this code (it is from RN template):
import { AppRegistry } from 'react-native';
import App from './App';
AppRegistry.registerComponent('MyApp', () => App);
Create MyApp/App.js
:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
- start packager
npm start
from root project folder (MyApp
)
- run app from xcode, you should see loading indicator and then RN rendered screen with "Welcome to React Native!"
Packager
- You also should add packager build step to embed compiled js to app bundle
main.jsbundle
so it can be run without packager dev server.
Add script step to MyApp target's Build phases with this content:
export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh
This steps works for me.