{"_id":"5a06037134873d0010b3920e","category":{"_id":"5a06037134873d0010b39200","version":"5a06037134873d0010b391fe","project":"578c4badbd223d2000cc1441","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2017-03-17T18:59:29.780Z","from_sync":false,"order":1,"slug":"getting-started-ios","title":"iOS - Platform Setup"},"parentDoc":null,"project":"578c4badbd223d2000cc1441","user":"578c4a62bd223d2000cc143e","version":{"_id":"5a06037134873d0010b391fe","project":"578c4badbd223d2000cc1441","__v":1,"createdAt":"2017-11-10T19:52:17.163Z","releaseDate":"2017-11-10T19:52:17.163Z","categories":["5a06037134873d0010b391ff","5a06037134873d0010b39200","5a06037134873d0010b39201","5a06037134873d0010b39202","5a06037134873d0010b39203","5a06037134873d0010b39204"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"2.1.0","version":"2.1.0"},"__v":0,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-07-18T22:08:16.973Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":1,"body":"This documentation was adapted from React Native's [Integration with Existing Apps](https://facebook.github.io/react-native/docs/integration-with-existing-apps.html) guide.\n\n# Integrating with Existing iOS Application\n\nThe instructions below explain how to integrate ViroReact with your existing iOS project. We use the following github project as an example: https://github.com/JoelMarcey/iOS-2048.\n\nWe'll take this app and modify it by adding a ViroReact VR or AR view to the application. This doc will show you how to:\n1) Add React Native and ViroReact to your existing iOS application.\n2) Launch ViroReact from your existing iOS Application.\n3) Pass parameters from your native app to Viro.\n\n**Note that the following has been tested with React Native 0.47.2**\n\n## Prerequisite\n\nComplete the first 7 steps of the [Set up Xcode with Viro](doc:starting-a-new-viro-project-1) guide to install dependencies.\n\n## Checkout an existing iOS app\n\nSince we're modifying the [iOS-2048](https://github.com/JoelMarcey/iOS-2048) app, we'll need to check it out. From your terminal, navigate to where you'd like to check out the project and run: \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"git clone https://github.com/JoelMarcey/iOS-2048.git\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nThis should pull the repository down into an `iOS-2048` directory.\n\n## Adding package.json and node_modules to your project.\n\n### package.json\n\nIn the root of the project (`/iOS-2048/`) create a file with the following content and name it `package.json`.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n  \\\"name\\\": \\\"NumberTileGame\\\",\\n  \\\"version\\\": \\\"0.0.1\\\",\\n  \\\"private\\\": true,\\n  \\\"scripts\\\": {\\n    \\\"start\\\": \\\"node node_modules/react-native/local-cli/cli.js start\\\"\\n  },\\n  \\\"dependencies\\\": {\\n    \\\"react\\\": \\\"16.0.0-alpha.12\\\",\\n    \\\"react-native\\\": \\\"0.47.2\\\",\\n    \\\"react-viro\\\": \\\"2.0.0\\\"\\n  }\\n}  \",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nAfter you've added the file, run the follow command at the project root:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"npm install\",\n      \"language\": \"shell\"\n    }\n  ]\n}\n[/block]\n\n### Podfile\n\nSince this project does not already uses Cocoapods, directory to create a `Podfile`:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"pod init\",\n      \"language\": \"shell\"\n    }\n  ]\n}\n[/block]\nEdit your Podfile to look like the following:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"platform :ios, '9.3'\\n\\n#The target name is the name of your project.\\ntarget 'NumberTileGame' do\\n  pod 'ViroReact', :path => '../node_modules/react-viro/ios/'\\nend\",\n      \"language\": \"yaml\"\n    }\n  ]\n}\n[/block]\nConfigure line 2 above with the right path to the `node_modules/react-viro` directory if you decided to put your `package.json` in another directory.\n\n**If you are already using CocoaPods, then simply add `ViroReact` to your `Podfile`. **\n\nOnce you've made your changes, from the terminal, run:\n\n`pod repo update` and `pod install`\n\n###index.js\n\nCreate a file called `index.js` at the directory root and add the below content:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"'use strict';\\n\\nimport React, { Component } from 'react';\\n\\nimport { AppRegistry } from 'react-native';\\n\\nimport {\\n  ViroSceneNavigator,\\n} from 'react-viro';\\n\\nvar HelloWorldScene = require('./js/TestScene');\\n\\nvar ViroSample = React.createClass({\\n  render: function() {\\n    // The 'viroAppProps={{...this.props}}' line below is used to pass\\n    // the initial properties from this base component to the ViroSceneNavigator\\n    // which will allow the scenes to access them.\\n  \\tlet viroAppProps = {...this.props};\\n    \\n    return (\\n      <ViroSceneNavigator\\n        initialScene={{\\n          scene: HelloWorldScene,\\n        }}\\n        viroAppProps={viroAppProps}\\n        vrModeEnabled={viroAppProps.vrModeEnabled}\\n        apiKey={\\\"YOUR_API_KEY_HERE\\\"}\\n      />\\n    );\\n  }\\n});\\n\\nAppRegistry.registerComponent('RNHighScores', () => ViroSample);\\n\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nThis file is the main entry point into the iOS version of your application. Essentially, it creates a basic React class (`ViroSampleApp`) which wraps a `ViroSceneNavigator` and sets the initial scene to a `TestScene` module defined at `./js/TestScene` which we'll create in the next step. It then registers `RNHighScores` with the AppRegistry so that we can launch it by name from objective-C.\n\nNext, replace the text `YOUR_API_KEY_HERE` on line 26 above with the API Key you received.\n\n## TestScene.js\nCreate a separate directory at the root named `js`\n\nCreate a file in it called `TestScene.js` with the below contents:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"'use strict';\\n\\nimport React, { Component } from 'react';\\n\\nimport {StyleSheet} from 'react-native';\\n\\nimport {\\n  ViroScene,\\n  ViroText,\\n  Viro360Image,\\n} from 'react-viro';\\n\\nvar TestScene = React.createClass({\\n\\n  render: function() {\\n   \\n    var highScore = \\\"High Score: \\\" + this.props.sceneNavigator.viroAppProps.highScore;\\n    return (\\n     <ViroScene>\\n       <Viro360Image source={require('./res/guadalupe_360.jpg')} />\\n       <ViroText width={2} text={highScore} style={styles.helloWorldTextStyle} position={[0, 0, -4]} />\\n     </ViroScene>\\n    );\\n  },\\n});\\n\\nvar styles = StyleSheet.create({\\n helloWorldTextStyle: {\\n    fontFamily: 'Arial',\\n    fontSize: 30,\\n    color: '#ffffff',\\n    textAlignVertical: 'center',\\n    textAlign: 'center',\\n  },\\n});\\n\\nmodule.exports = TestScene;\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nThis scene simply renders a text view with the high score parameter passed from the application.\n\n### Resources\n\nWe recommend keeping all your resources within one directory in your application for better file management.\n\nCreate a `res` directory at the root of your workspace, download [this](https://s3-us-west-2.amazonaws.com/viro/guadalupe_360.jpg) image and place it in the directory you just created.\n\n## Native Changes\n\nNow that we have all the ViroReact components set-up, it's time to modify your iOS code to enter a ViroReact Scene. The easiest way to do this is to add an event (button click, etc) to an existing view controller. Then in the event callback, create and launch a  `UIViewController` with a `RCTRootView` containing the ViroReact app specified in the above index.js file.\n\nLet's do this with the example we are using. \n\nFirst let's edit the apps AppDelegate, in this case F3HAppDelegate. Open F3HAppDelegate.h and add the property **isViroSceneDisplaying**: \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"#import <UIKit/UIKit.h>\\n\\n:::at:::interface F3HAppDelegate : UIResponder <UIApplicationDelegate>\\n\\n@property (strong, nonatomic) UIWindow *window;\\n@property (nonatomic, assign) BOOL isViroSceneDisplaying;\\n\\n@end\",\n      \"language\": \"objectivec\"\n    }\n  ]\n}\n[/block]\nNow add the method below to F3HAppDelegate.m:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {\\n  // Force the oprientation into landscape mode if we are displaying a ViroSceneViewController.\\n  if(self.isViroSceneDisplaying) {\\n    return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationLandscapeRight);\\n  }\\n  return UIInterfaceOrientationMaskAllButUpsideDown;\\n}\",\n      \"language\": \"objectivec\"\n    }\n  ]\n}\n[/block]\nThis ensures that when a ViroReact scene displays the rotation will be set to landscape at the app level.\nNow lets create a UIViewController derived class called `ViroViewController`. The header file should look like below:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"//\\n//  ViroViewController.h\\n//  NumberTileGame\\n//\\n\\n#import <Foundation/Foundation.h>\\n\\n@interface ViroViewController : UIViewController\\n  -(id)initWithVREnabledMode:(BOOL)vrEnabledMode;\\n\\n@property (nonatomic, assign) BOOL vrMode;\\n@end\",\n      \"language\": \"objectivec\"\n    }\n  ]\n}\n[/block]\nNow in `ViroViewController.m` add the following methods so the file looks like below:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"//\\n//  ViroViewController.m\\n//  NumberTileGame\\n//\\n\\n#import \\\"ViroViewController.h\\\"\\n#import \\\"F3HAppDelegate.h\\\"\\n#import \\\"VRTNotifications.h\\\"\\n\\n@implementation ViroViewController\\n\\n-(id)initWithVREnabledMode:(BOOL)vrEnabledMode {\\n  self = [super init];\\n  self.vrMode = vrEnabledMode;\\n  return self;\\n}\\n\\n- (void)viewWillAppear:(BOOL)animated {\\n    F3HAppDelegate *delegate = (F3HAppDelegate *)[[UIApplication sharedApplication] delegate];\\n    delegate.isViroSceneDisplaying = YES;\\n  \\n  // register for the exit notification\\n  [[NSNotificationCenter defaultCenter] addObserver:self\\n                                           selector:@selector(exitReactViro)\\n                                               name:kVRTOnExitViro\\n                                             object:nil];\\n  \\n}\\n\\n- (UIInterfaceOrientationMask)supportedInterfaceOrientations {\\n  return (UIInterfaceOrientationLandscapeLeft);\\n}\\n\\n-(BOOL)shouldAutorotate {\\n  return NO;\\n}\\n\\n- (void)exitReactViro {\\n  dispatch_async(dispatch_get_main_queue(), ^{\\n    F3HAppDelegate *delegate = (F3HAppDelegate *)[[UIApplication sharedApplication] delegate];\\n    delegate.isViroSceneDisplaying = NO;\\n    if(self.vrMode) {\\n      [self willMoveToParentViewController:nil];\\n      [self.view removeFromSuperview];\\n      [self removeFromParentViewController];\\n    } else {\\n      [self dismissViewControllerAnimated:NO completion:nil];\\n    }\\n    [[NSNotificationCenter defaultCenter] removeObserver:self];\\n  });\\n}\\n\\n@end\\n\\n  \\n  \",\n      \"language\": \"objectivec\"\n    }\n  ]\n}\n[/block]\nLet's go thru the above code in detail to understand what it's doing. The rotation methods **shouldAutorotate** and **supportedInterfaceOrientations** ensure that when we launch into VR or 360 mode(fullscreen mode that doesn't require a cardboard headset) we ensure the app stays in landscape mode.\n\nThe **viewDidAppear** appear method is invoked when our controller is about to appear. In this method we do the following: \n1) Tell our appDelegate we are displaying our VR scene by setting **isViroSceneDisplaying** to true.\n2) Register to listen for notification **kVRTOnExitViro**. This is a notification that ViroReact invokes to let you know that ViroReact is exiting so you can perform your own cleanup. In this case we state we want to invoke the **exitReactViro** method.\n\nThe **exitReactViro** method is invoked when we exit the ViroReact View. Depending on if vrMode is true or false, we signal to our parent controller that we are dismissing. In addition, we tell the appDelegate we are no longer displaying a ViroReact scene and remove ourselves as a listener for NSNotificationCenter.\n\nNow let's use our new ViroViewController and integrate it into our current app.\n\nFirst, add the following imports to `F3HController.m`:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"#import \\\"ViroViewController.h\\\"\\n#import <React/RCTRootView.h>\",\n      \"language\": \"objectivec\"\n    }\n  ]\n}\n[/block]\nAdd a method call `highScoreButtonPressed` to `F3HController.m` like below:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"- (IBAction)highScoreButtonPressed:(id)sender {\\n  BOOL vrEnabled = true;\\n  NSDictionary *initialProperties =\\n  @{\\n    @\\\"highScore\\\" : @\\\"40\\\",\\n   @\\\"vrModeEnabled\\\" : [NSNumber numberWithBool:vrEnabled]\\n   };\\n  \\n  NSURL *jsCodeLocation = nil;\\n#ifdef DEBUG\\n  jsCodeLocation = [NSURL URLWithString:@\\\"http://<YOUR IP or NGROK ENDPOINT>/index.bundle?platform=ios\\\"];\\n#else\\n  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@\\\"index\\\"                                                                 fallbackResource:nil];\\n#endif\\n\\n  RCTRootView *rootView =\\n  [[RCTRootView alloc] initWithBundleURL : jsCodeLocation\\n                       moduleName        : @\\\"RNHighScores\\\"\\n                       initialProperties :initialProperties\\n                        launchOptions    : nil];\\n  ViroViewController *vc = [[ViroViewController alloc] initWithVREnabledMode:vrEnabled];\\n  vc.view = rootView;\\n\\n  //present the controller differently depending on whether we are in vr mode or not.\\n  if(vrEnabled) {\\n    [self addChildViewController:vc];\\n    vc.view.frame = CGRectMake(0,   0,self.view.frame.size.width,self.view.frame.size.height);\\n    [self.view addSubview:vc.view];\\n    [vc didMoveToParentViewController:self];\\n  } else{\\n      vc.modalPresentationStyle = UIModalPresentationFullScreen;\\n      [self presentViewController:vc animated:YES completion:nil];\\n  }\\n}\",\n      \"language\": \"objectivec\"\n    }\n  ]\n}\n[/block]\nOn line 11 above, replace `<YOUR IP or NGROK ENDPOINT>` with your ngrok url (`aaaaaaa.ngrok.io`) or ip address (`10.0.0.0:8081`). \n\nThe method we just added does the following: \n1) Creates a dictionary that gets passed to the initial javascript file `index.js`.\n2) If we are in debug our source js location is assumed to be using the react native packager server which can run from your local IP or ngrok endpoint. In release builds, the Javascript files are bundled into the application and are loaded from disk during runtime.\n3) We then create a `RCTRootView` and set is at the view of our new controller.\n4) Next, we present the controller. Depending on whether we want stereographic vr view that requires a cardboard headset(vrEnabled = true) or a full screen 360 mode experience(vrEnabled=false), we present the controller differently due to how Google Cardboard SDK works.\n\n## Adding a button to launch Viro\n\nOpen the `Main_iPhone.storyboard` file, in the main view, add a button and change its text to `High Score`.\n\nNow hook up the `High Score` button to the new method `highScoreButtonPressed` using Interface Builder like below:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/a95d65e-Screen_Shot_2017-03-30_at_2.10.28_AM.png\",\n        \"Screen Shot 2017-03-30 at 2.10.28 AM.png\",\n        1538,\n        1128,\n        \"#353435\"\n      ]\n    }\n  ]\n}\n[/block]\nAnd *Voilà!* you've now added a ViroReact Scene into your application. \n\n##Modify Build Settings\nIn the build settings of the project do the following: \n1) Change enable Bitcode to **No**:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/de2e3a8-Screen_Shot_2017-03-30_at_2.19.03_AM.png\",\n        \"Screen Shot 2017-03-30 at 2.19.03 AM.png\",\n        1554,\n        788,\n        \"#40322b\"\n      ]\n    }\n  ]\n}\n[/block]\n2) Set deployment target to iOS 9.3 or higher.\n3) Set Build Settings -> Linking -> Other Linker Flags to the following 3 values:\n  * $(inheirited)\n  * -ObjC\n  * -lc++\n4) Set Build Settings -> Linking -> Runpath Search Paths to `@executable_path/Frameworks`\n5) Under the `NumberTileGame` Group in the Navigator, add a new group called `Libraries`\n6) Add two React Native libraries to Libraries. Right-click on Libraries -> Add Files to \"NumberTileGame...\" \n  * Add `iOS-2048/node_modules/react-native/React/React.xcodeproj`\n  * Add `iOS-2048/node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj`\n7) In the NumberTileGame Project, `NumberTileGame` target -> General -> Linked Frameworks and Libraries, add `libReact.a` and `libRCTWebSocket.a`\n\n##Run the App\nNow you are almost ready to run your ViroReact integrated app:\n1) In terminal, where your .xcodeproj is located, run npm start to launch the react packager that will retrieve your JS files from xcode.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"npm start\\n\",\n      \"language\": \"shell\"\n    }\n  ]\n}\n[/block]\n2) Find your IP or your ngrok endpoint if you run 'ngrok http 8081' on the terminal. Cut and paste that into where it says <YOUR IP or NGROK ENDPOINT> in F3HController.m\n3) Run your app in debug!\n\nYou now have added ViroReact to an existing app!\n\nTap on the high score text to see the VR mode launch and display the text that was passed in from the native code!\n\n##Running your app in fullscreen 360 mode.\n\nSometimes you may wish to launch into a full screen mode, rather than a a stereoscopic mode that requires a headset. To do this, in the above code, modify the vrEnabled flag to be false. This will launch the app in full screen 360 mode. \n\nIf you wish to have the user choose what they prefer, then it's best to add an iOS dialog before you push the view controller that asks them if they have a headset or not. The vrEnabled flag can be set based on what they choose.\n\n## Adding AR\n\nReplace the code in `index.js` and the files in the `js/` directory with AR code and relaunch the application.\n\n## Building for Release.\nTo run your new VR Enabled iOS App in release you'll need to add a new 'Run Script' build phase.\nPaste the following code into the the run script phase:\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"export NODE_BINARY=node\\n\\n$SRCROOT/node_modules/react-native/packager/react-native-xcode.sh\",\n      \"language\": \"shell\"\n    }\n  ]\n}\n[/block]\nThis above script will compile and bundle the necessary assets and js code into your app for release.\nHere's how it looks it Xcode for reference: \n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/cbf6afe-Screen_Shot_2017-03-30_at_7.14.44_PM.png\",\n        \"Screen Shot 2017-03-30 at 7.14.44 PM.png\",\n        1602,\n        864,\n        \"#dadad8\"\n      ]\n    }\n  ]\n}\n[/block]\nNow select the NumbeTileGame scheme and switch the build type to 'Release' like below: \n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/e6602bd-Screen_Shot_2017-03-30_at_7.19.47_PM.png\",\n        \"Screen Shot 2017-03-30 at 7.19.47 PM.png\",\n        1770,\n        896,\n        \"#eaeaea\"\n      ]\n    }\n  ]\n}\n[/block]\nCompile and build and the app. It should run in release without connecting to any react package server. This is how your app will look in production!\n\n## Troubleshooting\n\nPlease refer to the troubleshooting section at the bottom of the [Installing Viro](doc:starting-a-new-viro-project-1#section-troubleshooting) guide.","excerpt":"","slug":"integrate-project-with-viro","type":"basic","title":"Integrating Existing Projects (iOS)"}

Integrating Existing Projects (iOS)


This documentation was adapted from React Native's [Integration with Existing Apps](https://facebook.github.io/react-native/docs/integration-with-existing-apps.html) guide. # Integrating with Existing iOS Application The instructions below explain how to integrate ViroReact with your existing iOS project. We use the following github project as an example: https://github.com/JoelMarcey/iOS-2048. We'll take this app and modify it by adding a ViroReact VR or AR view to the application. This doc will show you how to: 1) Add React Native and ViroReact to your existing iOS application. 2) Launch ViroReact from your existing iOS Application. 3) Pass parameters from your native app to Viro. **Note that the following has been tested with React Native 0.47.2** ## Prerequisite Complete the first 7 steps of the [Set up Xcode with Viro](doc:starting-a-new-viro-project-1) guide to install dependencies. ## Checkout an existing iOS app Since we're modifying the [iOS-2048](https://github.com/JoelMarcey/iOS-2048) app, we'll need to check it out. From your terminal, navigate to where you'd like to check out the project and run: [block:code] { "codes": [ { "code": "git clone https://github.com/JoelMarcey/iOS-2048.git", "language": "text" } ] } [/block] This should pull the repository down into an `iOS-2048` directory. ## Adding package.json and node_modules to your project. ### package.json In the root of the project (`/iOS-2048/`) create a file with the following content and name it `package.json`. [block:code] { "codes": [ { "code": "{\n \"name\": \"NumberTileGame\",\n \"version\": \"0.0.1\",\n \"private\": true,\n \"scripts\": {\n \"start\": \"node node_modules/react-native/local-cli/cli.js start\"\n },\n \"dependencies\": {\n \"react\": \"16.0.0-alpha.12\",\n \"react-native\": \"0.47.2\",\n \"react-viro\": \"2.0.0\"\n }\n} ", "language": "javascript" } ] } [/block] After you've added the file, run the follow command at the project root: [block:code] { "codes": [ { "code": "npm install", "language": "shell" } ] } [/block] ### Podfile Since this project does not already uses Cocoapods, directory to create a `Podfile`: [block:code] { "codes": [ { "code": "pod init", "language": "shell" } ] } [/block] Edit your Podfile to look like the following: [block:code] { "codes": [ { "code": "platform :ios, '9.3'\n\n#The target name is the name of your project.\ntarget 'NumberTileGame' do\n pod 'ViroReact', :path => '../node_modules/react-viro/ios/'\nend", "language": "yaml" } ] } [/block] Configure line 2 above with the right path to the `node_modules/react-viro` directory if you decided to put your `package.json` in another directory. **If you are already using CocoaPods, then simply add `ViroReact` to your `Podfile`. ** Once you've made your changes, from the terminal, run: `pod repo update` and `pod install` ###index.js Create a file called `index.js` at the directory root and add the below content: [block:code] { "codes": [ { "code": "'use strict';\n\nimport React, { Component } from 'react';\n\nimport { AppRegistry } from 'react-native';\n\nimport {\n ViroSceneNavigator,\n} from 'react-viro';\n\nvar HelloWorldScene = require('./js/TestScene');\n\nvar ViroSample = React.createClass({\n render: function() {\n // The 'viroAppProps={{...this.props}}' line below is used to pass\n // the initial properties from this base component to the ViroSceneNavigator\n // which will allow the scenes to access them.\n \tlet viroAppProps = {...this.props};\n \n return (\n <ViroSceneNavigator\n initialScene={{\n scene: HelloWorldScene,\n }}\n viroAppProps={viroAppProps}\n vrModeEnabled={viroAppProps.vrModeEnabled}\n apiKey={\"YOUR_API_KEY_HERE\"}\n />\n );\n }\n});\n\nAppRegistry.registerComponent('RNHighScores', () => ViroSample);\n", "language": "javascript" } ] } [/block] This file is the main entry point into the iOS version of your application. Essentially, it creates a basic React class (`ViroSampleApp`) which wraps a `ViroSceneNavigator` and sets the initial scene to a `TestScene` module defined at `./js/TestScene` which we'll create in the next step. It then registers `RNHighScores` with the AppRegistry so that we can launch it by name from objective-C. Next, replace the text `YOUR_API_KEY_HERE` on line 26 above with the API Key you received. ## TestScene.js Create a separate directory at the root named `js` Create a file in it called `TestScene.js` with the below contents: [block:code] { "codes": [ { "code": "'use strict';\n\nimport React, { Component } from 'react';\n\nimport {StyleSheet} from 'react-native';\n\nimport {\n ViroScene,\n ViroText,\n Viro360Image,\n} from 'react-viro';\n\nvar TestScene = React.createClass({\n\n render: function() {\n \n var highScore = \"High Score: \" + this.props.sceneNavigator.viroAppProps.highScore;\n return (\n <ViroScene>\n <Viro360Image source={require('./res/guadalupe_360.jpg')} />\n <ViroText width={2} text={highScore} style={styles.helloWorldTextStyle} position={[0, 0, -4]} />\n </ViroScene>\n );\n },\n});\n\nvar styles = StyleSheet.create({\n helloWorldTextStyle: {\n fontFamily: 'Arial',\n fontSize: 30,\n color: '#ffffff',\n textAlignVertical: 'center',\n textAlign: 'center',\n },\n});\n\nmodule.exports = TestScene;", "language": "javascript" } ] } [/block] This scene simply renders a text view with the high score parameter passed from the application. ### Resources We recommend keeping all your resources within one directory in your application for better file management. Create a `res` directory at the root of your workspace, download [this](https://s3-us-west-2.amazonaws.com/viro/guadalupe_360.jpg) image and place it in the directory you just created. ## Native Changes Now that we have all the ViroReact components set-up, it's time to modify your iOS code to enter a ViroReact Scene. The easiest way to do this is to add an event (button click, etc) to an existing view controller. Then in the event callback, create and launch a `UIViewController` with a `RCTRootView` containing the ViroReact app specified in the above index.js file. Let's do this with the example we are using. First let's edit the apps AppDelegate, in this case F3HAppDelegate. Open F3HAppDelegate.h and add the property **isViroSceneDisplaying**: [block:code] { "codes": [ { "code": "#import <UIKit/UIKit.h>\n\n@interface F3HAppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n@property (nonatomic, assign) BOOL isViroSceneDisplaying;\n\n@end", "language": "objectivec" } ] } [/block] Now add the method below to F3HAppDelegate.m: [block:code] { "codes": [ { "code": "- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {\n // Force the oprientation into landscape mode if we are displaying a ViroSceneViewController.\n if(self.isViroSceneDisplaying) {\n return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationLandscapeRight);\n }\n return UIInterfaceOrientationMaskAllButUpsideDown;\n}", "language": "objectivec" } ] } [/block] This ensures that when a ViroReact scene displays the rotation will be set to landscape at the app level. Now lets create a UIViewController derived class called `ViroViewController`. The header file should look like below: [block:code] { "codes": [ { "code": "//\n// ViroViewController.h\n// NumberTileGame\n//\n\n#import <Foundation/Foundation.h>\n\n@interface ViroViewController : UIViewController\n -(id)initWithVREnabledMode:(BOOL)vrEnabledMode;\n\n@property (nonatomic, assign) BOOL vrMode;\n@end", "language": "objectivec" } ] } [/block] Now in `ViroViewController.m` add the following methods so the file looks like below: [block:code] { "codes": [ { "code": "//\n// ViroViewController.m\n// NumberTileGame\n//\n\n#import \"ViroViewController.h\"\n#import \"F3HAppDelegate.h\"\n#import \"VRTNotifications.h\"\n\n@implementation ViroViewController\n\n-(id)initWithVREnabledMode:(BOOL)vrEnabledMode {\n self = [super init];\n self.vrMode = vrEnabledMode;\n return self;\n}\n\n- (void)viewWillAppear:(BOOL)animated {\n F3HAppDelegate *delegate = (F3HAppDelegate *)[[UIApplication sharedApplication] delegate];\n delegate.isViroSceneDisplaying = YES;\n \n // register for the exit notification\n [[NSNotificationCenter defaultCenter] addObserver:self\n selector:@selector(exitReactViro)\n name:kVRTOnExitViro\n object:nil];\n \n}\n\n- (UIInterfaceOrientationMask)supportedInterfaceOrientations {\n return (UIInterfaceOrientationLandscapeLeft);\n}\n\n-(BOOL)shouldAutorotate {\n return NO;\n}\n\n- (void)exitReactViro {\n dispatch_async(dispatch_get_main_queue(), ^{\n F3HAppDelegate *delegate = (F3HAppDelegate *)[[UIApplication sharedApplication] delegate];\n delegate.isViroSceneDisplaying = NO;\n if(self.vrMode) {\n [self willMoveToParentViewController:nil];\n [self.view removeFromSuperview];\n [self removeFromParentViewController];\n } else {\n [self dismissViewControllerAnimated:NO completion:nil];\n }\n [[NSNotificationCenter defaultCenter] removeObserver:self];\n });\n}\n\n@end\n\n \n ", "language": "objectivec" } ] } [/block] Let's go thru the above code in detail to understand what it's doing. The rotation methods **shouldAutorotate** and **supportedInterfaceOrientations** ensure that when we launch into VR or 360 mode(fullscreen mode that doesn't require a cardboard headset) we ensure the app stays in landscape mode. The **viewDidAppear** appear method is invoked when our controller is about to appear. In this method we do the following: 1) Tell our appDelegate we are displaying our VR scene by setting **isViroSceneDisplaying** to true. 2) Register to listen for notification **kVRTOnExitViro**. This is a notification that ViroReact invokes to let you know that ViroReact is exiting so you can perform your own cleanup. In this case we state we want to invoke the **exitReactViro** method. The **exitReactViro** method is invoked when we exit the ViroReact View. Depending on if vrMode is true or false, we signal to our parent controller that we are dismissing. In addition, we tell the appDelegate we are no longer displaying a ViroReact scene and remove ourselves as a listener for NSNotificationCenter. Now let's use our new ViroViewController and integrate it into our current app. First, add the following imports to `F3HController.m`: [block:code] { "codes": [ { "code": "#import \"ViroViewController.h\"\n#import <React/RCTRootView.h>", "language": "objectivec" } ] } [/block] Add a method call `highScoreButtonPressed` to `F3HController.m` like below: [block:code] { "codes": [ { "code": "- (IBAction)highScoreButtonPressed:(id)sender {\n BOOL vrEnabled = true;\n NSDictionary *initialProperties =\n @{\n @\"highScore\" : @\"40\",\n @\"vrModeEnabled\" : [NSNumber numberWithBool:vrEnabled]\n };\n \n NSURL *jsCodeLocation = nil;\n#ifdef DEBUG\n jsCodeLocation = [NSURL URLWithString:@\"http://<YOUR IP or NGROK ENDPOINT>/index.bundle?platform=ios\"];\n#else\n jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@\"index\" fallbackResource:nil];\n#endif\n\n RCTRootView *rootView =\n [[RCTRootView alloc] initWithBundleURL : jsCodeLocation\n moduleName : @\"RNHighScores\"\n initialProperties :initialProperties\n launchOptions : nil];\n ViroViewController *vc = [[ViroViewController alloc] initWithVREnabledMode:vrEnabled];\n vc.view = rootView;\n\n //present the controller differently depending on whether we are in vr mode or not.\n if(vrEnabled) {\n [self addChildViewController:vc];\n vc.view.frame = CGRectMake(0, 0,self.view.frame.size.width,self.view.frame.size.height);\n [self.view addSubview:vc.view];\n [vc didMoveToParentViewController:self];\n } else{\n vc.modalPresentationStyle = UIModalPresentationFullScreen;\n [self presentViewController:vc animated:YES completion:nil];\n }\n}", "language": "objectivec" } ] } [/block] On line 11 above, replace `<YOUR IP or NGROK ENDPOINT>` with your ngrok url (`aaaaaaa.ngrok.io`) or ip address (`10.0.0.0:8081`). The method we just added does the following: 1) Creates a dictionary that gets passed to the initial javascript file `index.js`. 2) If we are in debug our source js location is assumed to be using the react native packager server which can run from your local IP or ngrok endpoint. In release builds, the Javascript files are bundled into the application and are loaded from disk during runtime. 3) We then create a `RCTRootView` and set is at the view of our new controller. 4) Next, we present the controller. Depending on whether we want stereographic vr view that requires a cardboard headset(vrEnabled = true) or a full screen 360 mode experience(vrEnabled=false), we present the controller differently due to how Google Cardboard SDK works. ## Adding a button to launch Viro Open the `Main_iPhone.storyboard` file, in the main view, add a button and change its text to `High Score`. Now hook up the `High Score` button to the new method `highScoreButtonPressed` using Interface Builder like below: [block:image] { "images": [ { "image": [ "https://files.readme.io/a95d65e-Screen_Shot_2017-03-30_at_2.10.28_AM.png", "Screen Shot 2017-03-30 at 2.10.28 AM.png", 1538, 1128, "#353435" ] } ] } [/block] And *Voilà!* you've now added a ViroReact Scene into your application. ##Modify Build Settings In the build settings of the project do the following: 1) Change enable Bitcode to **No**: [block:image] { "images": [ { "image": [ "https://files.readme.io/de2e3a8-Screen_Shot_2017-03-30_at_2.19.03_AM.png", "Screen Shot 2017-03-30 at 2.19.03 AM.png", 1554, 788, "#40322b" ] } ] } [/block] 2) Set deployment target to iOS 9.3 or higher. 3) Set Build Settings -> Linking -> Other Linker Flags to the following 3 values: * $(inheirited) * -ObjC * -lc++ 4) Set Build Settings -> Linking -> Runpath Search Paths to `@executable_path/Frameworks` 5) Under the `NumberTileGame` Group in the Navigator, add a new group called `Libraries` 6) Add two React Native libraries to Libraries. Right-click on Libraries -> Add Files to "NumberTileGame..." * Add `iOS-2048/node_modules/react-native/React/React.xcodeproj` * Add `iOS-2048/node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj` 7) In the NumberTileGame Project, `NumberTileGame` target -> General -> Linked Frameworks and Libraries, add `libReact.a` and `libRCTWebSocket.a` ##Run the App Now you are almost ready to run your ViroReact integrated app: 1) In terminal, where your .xcodeproj is located, run npm start to launch the react packager that will retrieve your JS files from xcode. [block:code] { "codes": [ { "code": "npm start\n", "language": "shell" } ] } [/block] 2) Find your IP or your ngrok endpoint if you run 'ngrok http 8081' on the terminal. Cut and paste that into where it says <YOUR IP or NGROK ENDPOINT> in F3HController.m 3) Run your app in debug! You now have added ViroReact to an existing app! Tap on the high score text to see the VR mode launch and display the text that was passed in from the native code! ##Running your app in fullscreen 360 mode. Sometimes you may wish to launch into a full screen mode, rather than a a stereoscopic mode that requires a headset. To do this, in the above code, modify the vrEnabled flag to be false. This will launch the app in full screen 360 mode. If you wish to have the user choose what they prefer, then it's best to add an iOS dialog before you push the view controller that asks them if they have a headset or not. The vrEnabled flag can be set based on what they choose. ## Adding AR Replace the code in `index.js` and the files in the `js/` directory with AR code and relaunch the application. ## Building for Release. To run your new VR Enabled iOS App in release you'll need to add a new 'Run Script' build phase. Paste the following code into the the run script phase: [block:code] { "codes": [ { "code": "export NODE_BINARY=node\n\n$SRCROOT/node_modules/react-native/packager/react-native-xcode.sh", "language": "shell" } ] } [/block] This above script will compile and bundle the necessary assets and js code into your app for release. Here's how it looks it Xcode for reference: [block:image] { "images": [ { "image": [ "https://files.readme.io/cbf6afe-Screen_Shot_2017-03-30_at_7.14.44_PM.png", "Screen Shot 2017-03-30 at 7.14.44 PM.png", 1602, 864, "#dadad8" ] } ] } [/block] Now select the NumbeTileGame scheme and switch the build type to 'Release' like below: [block:image] { "images": [ { "image": [ "https://files.readme.io/e6602bd-Screen_Shot_2017-03-30_at_7.19.47_PM.png", "Screen Shot 2017-03-30 at 7.19.47 PM.png", 1770, 896, "#eaeaea" ] } ] } [/block] Compile and build and the app. It should run in release without connecting to any react package server. This is how your app will look in production! ## Troubleshooting Please refer to the troubleshooting section at the bottom of the [Installing Viro](doc:starting-a-new-viro-project-1#section-troubleshooting) guide.