[iOS] React Native 移植原生 iOS 平台项目

james7808 8年前
   <h2>(一)前言</h2>    <p>今天我们来看一下React Native移植到iOS原生应用,通过本节讲解,相信大家对于正在开发的iOS原生项目就可以移植到React Native平台中来,或者采取原生加RN混合开发模式啦。</p>    <p>刚创建的React Native技术交流5群( 386216878 ),欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送!</p>    <p>React更多的是作为MVC模式中的V视图层存在,所以该就非常容易嵌入到非React Native开发的应用中。实际上,该可以和常见的工具进行结合,例如CocoaPods( <a href="/misc/goto?guid=4958539574664641318" rel="nofollow,noindex">详细请点击进入了解</a> ).</p>    <h2>(二)准备工作</h2>    <p>1.安装CocoaPods     -这个相应大家如果之前做过iOS开发应该都清除的吧。安装命令:gem install  cocoapods</p>    <p>2.Node.js    -如果大家已经在Mac平台已经成功运行过React Native应用,那么该肯定是安装了(没安装,点击进入了解)。安装nvm的教程点击命令,该命令会进行安装最新的Node.js版本,然后配置好环境变量。最后你可以通过命令node来启动运行Node.js环境。大家可能也知道,通过nvm,大家可以安装多个Node.js版本并且很方便的进行切换选择。</p>    <p>3.间接着,你可以命令切换到你的项目的根目录,命令运行npm install react-native来进行安装react-native包依赖。</p>    <p>以上步骤完成之后,在你项目根目录上面会存在一个React Native包,该命名为node_modules,和.xcodeproj文件平级。</p>    <h2>(三)使用CocoaPods进行安装React Native库</h2>    <p>CocoaPods是iOS/Mac开发中的包管理器,我们需要使用CocoaPods来进行下载React Native。如果你到现在还没有安装CocoaPods,那么 <a href="/misc/goto?guid=4959673079734864518" rel="nofollow,noindex">请点击了解安装向导</a> ,至于具体怎么样安装相信大家看官方向导或者百度一下,就会了。</p>    <p>当你用CocoaPods进行工作的时候,需要往Podfile文件中添加如下的一些代码信息。如果你还没有改文件,可以在仙姑的根目录上面进行创建一下。具体需要添加的信息如下:</p>    <pre>  <code class="language-javascript"># Depending on how your project is organized, your node_modules directory may be  # somewhere else; tell CocoaPods where you've installed react-native from npm  pod 'React', :path => './node_modules/react-native', :subspecs => [    'Core',    'RCTImage',    'RCTNetwork',    'RCTText',    'RCTWebSocket',    # Add any other subspecs you want to use in your project  ]</code></pre>    <p>记住需要添加安装所有的组件模块依赖才可以,例如如果你需要使用<Text>元素,但是如果没有安装RCTText,那么不行啦。</p>    <p>然后运行命令进行安装: pod install</p>    <h2>(四)创建React Native应用</h2>    <p>下面你两个注意步骤:</p>    <p>1.应用的入口/根JavaScript文件必须包含你的实际React Native应用和其他组件</p>    <p>2.封装Objective-C代码,加载你的脚本代码和创建一个RCTRootView对象来显示和管理你的React Native组件。</p>    <p>现在我们开始创建啦:</p>    <p>首先创建一个文件夹来存放应用的React代码,然后新建一个简单的index.ios.js文件,具体命令如下:</p>    <pre>  <code class="language-javascript">$ mkdir ReactComponent  $ touch ReactComponent/index.ios.js</code></pre>    <p>复制和粘贴如下的代码到index.ios.js文件中,这是一个最简单的React Native应用啦;</p>    <pre>  <code class="language-javascript">'use strict';    import React, {    Text,    View  } from 'react-native';    conststyles = React.StyleSheet.create({    container: {      flex: 1,      backgroundColor: 'red'    }  });    class SimpleApp extends React.Component {    render() {      return (        <View style={styles.container}>          <Text>This is a simple application.</Text>        </View>      )    }  }    React.AppRegistry.registerComponent('SimpleApp', () => SimpleApp);</code></pre>    <p>上面代码中的SimpeApp就是你的模块名称,该名称请记住,后边需要用到的哦~</p>    <h2>(五)往应用中添加容器视图</h2>    <p>现在你需要一个容器视图来转载React Native组件,该可以为你应用中任何的UIView。</p>    <p><img src="https://simg.open-open.com/show/9be09a9e308d44f47b3449034b000aae.png"></p>    <p>当然了,为了我们的代码更加整洁干净,我们创建一个继承UIView的ReactView。你点击YourProject.xcworkspace(具体你本地的项目),然后创建一个新的类ReactView(当然你可以随你自己喜欢进行命名…)</p>    <pre>  <code class="language-javascript">// ReactView.h    #import <UIKit/UIKit.h>  @interface ReactView : UIView  @end</code></pre>    <p>然后在需要管理这个视图的ViewController中,添加关联。</p>    <pre>  <code class="language-javascript">// ViewController.m    @interface ViewController ()  @property (weak, nonatomic) IBOutlet ReactView *reactView;  @end</code></pre>    <p>[注意].如果你的是Swift应用,就不需要这一步。同时这边我为了简化的演示相关效果,已经禁用了AutoLayout了,但是在实际的开发中,那么就需要打开AutoLayout并且设置相关约束。</p>    <h2>(六)往容器视图中添加RCTRootView</h2>    <p>前面我们已经做了好多准备工作了,那么现在重点来了,最后在确定一遍,你准备好了没?现在我们需要来创建RCTRootView来引入React Native应用了。</p>    <p>在ReactView.m文件中,我们首先需要加载index.ios.bundle文件来初始化RCTRootView, index.ios.bundle文件会由React Native Server进行创建并且可以通过React Native服务访问到。这个我们之后的教程会讲解到啦。</p>    <pre>  <code class="language-javascript">NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];  // For production use, this `NSURL` could instead point to a pre-bundled file on disk:  //  //   NSURL *jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];  //  // To generate that file, run the curl command and add the output to your main Xcode build target:  //  //   curl http://localhost:8081/index.ios.bundle -o main.jsbundle  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation                                                      moduleName: @"SimpleApp"                                               initialProperties:nil                                                   launchOptions:nil];</code></pre>    <p>然后把它添加成ReactView的子视图</p>    <pre>  <code class="language-javascript">[self addSubview:rootView];  rootView.frame = self.bounds;</code></pre>    <h2>(七)Swift应用</h2>    <p>如果你的是Swift应用的话,那么需要你在ReactView.swift文件中添加如下代码:</p>    <pre>  <code class="language-javascript">import UIKit  import React    class ReactView: UIView {      let rootView: RCTRootView = RCTRootView(bundleURL: NSURL(string: "http://localhost:8081/index.ios.bundle?platform=ios"),      moduleName: "SimpleApp", initialProperties: nil, launchOptions: nil)      override func layoutSubviews() {      super.layoutSubviews()        loadReact()    }      func loadReact () {          addSubview(rootView)          rootView.frame = self.bounds    }  }</code></pre>    <p>最后你需要确定一下你的该视图有没有添加到视图容器中或者故事板文件中(StoryBoard)</p>    <h2>(八)启动开发服务器</h2>    <p>在项目根目录中,我们需要开启React Native开发服务器,具体命令如下:</p>    <pre>  <code class="language-javascript">(JS_DIR=`pwd`/ReactComponent;cd node_modules/react-native; npm run start -- --root $JS_DIR)</code></pre>    <p>以上的命令,可以开启React Native开发服务,来构建我们的bundle文件。--root选项用来标注React Native应用所在的根目录。我们当前的例子是ReactComponents目录,在该文件夹中有一个index.ios.js文件。服务器启动之后会进行打包出来index.ios.bundle文件,然后让我们可以通过http://localhost:8081/index.ios.bundle进行访问。</p>    <h2>(九)更新App Transport Security</h2>    <p>在iOS9.0开始或者更高版本的系统中,除非特别配置,否则我们的应用是不能通过http访问localhost主机服务器的。具体解决方案可以查看: <a href="/misc/goto?guid=4959673079830136826" rel="nofollow,noindex">http://stackoverflow.com/questions/31254725/transport-security-has-blocked-a-cleartext-http</a></p>    <p>解决方案:推荐大家在应用的Info.plist文件作如下修改,把localhost本机访问排查例外项。</p>    <pre>  <code class="language-javascript"><key>NSAppTransportSecurity</key>  <dict>      <key>NSExceptionDomains</key>      <dict>          <key>localhost</key>          <dict>              <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>              <true/>          </dict>      </dict>  </dict></code></pre>    <p>如果大家没有这样做,那么可能会遇到Could not connect to development server的错误哦</p>    <h2>(十)编译和运行</h2>    <p>现在开始编译和运行你的应用,你会发现你的React Native应用运行在ReactView视图容器中了,具体截图如下</p>    <p><img src="https://simg.open-open.com/show/d4e276288a0a342b69620d42af72eedf.png"></p>    <p>注意在模拟器调试中我们可以实现热加载的(只要修改了JS代码,模拟器页面自动刷新的效果,确保在Build Settings->Preprocessor Macros中设置DEBUG=1)</p>    <h2>(十一)最后总结</h2>    <p>该效果的底层机制为,当RCTRootView被初始化的时候,该会从React Native开发服务器中下载并且解析加载bundle文件。这就意味着我们我们只要实现自己的视图容器或者ViewController,然后引入RCTRootView,该会进行加载渲染我们的React组件。特别说一下当前官方文档的官方实例代码 <a href="/misc/goto?guid=4959673079914786439" rel="nofollow,noindex">点击获取</a></p>    <p>今天我们主要学习了一下怎么样将React Native移植到iOS平台。大家有问题可以加一下群React Native技术交流5群(386216878).或者底下进行回复一下。</p>    <p>via: http://www.tuicool.com//articles/2A3iQ3m</p>