7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

既存アプリに ReactNative を組み込む

Last updated at Posted at 2018-06-03

ゴール

Xcode, AndroidStudio で適当にさらのネイティブアプリを作成し、任意のアクションによって ReactNative モジュール立ち上げる。
タイトルと乖離があるけど、これができれば既存のアプリを組み込むのも普通にできる。

前提

  • iOS それなりにわかる
    • 言語は Swift
  • Android それなりにわかる
    • 言語は Kotlin
  • ReactNative それなりにわかる

バージョン情報

$ react-native -v
react-native-cli: 2.0.1
react-native: 0.55.4

手順

RN プロジェクト作成

react-native-cli で react-native プロジェクトを作成

$ react-native init rn_integrated_native # or your project name

プロジェクトディレクトリに移動

$ cd rn_integrated_native

react-native-cli で生成されたネイティブモジュールを削除

$ rm -rf ios android

iOS プロジェクトの作成

Xcode でプロジェクトを作成して、先ほど作った RN プロジェクトのルートに保存

$ tree -L 2 -I 'node_modules'
.
├── App.js
├── app.json
├── index.js
├── package.json
├── rn_integrated_native
│   ├── rn_integrated_native
│   └── rn_integrated_native.xcodeproj
└── yarn.lock

3 directories, 5 files

保存した iOS プロジェクトのディレクトリ名を ios に変更

$ mv rn_integrated_native ios
$ $ tree -L 2 -I 'node_modules'
.
├── App.js
├── app.json
├── index.js
├── ios
│   ├── rn_integrated_native
│   ├── rn_integrated_native.xcodeproj
├── package.json
└── yarn.lock

以上の手順は Android にいても同様

iOS プロジェクトに RN を組み込む

cocoapods はある

$ pod --version
1.5.0

以下は特に断りのない限り ios ディレクトリで作業

$ pod init

下記のコードを Podfile にペースト

platform :ios, '10.0'

plugin 'cocoapods-fix-react-native'

target 'rn_integrated_native' do
  use_frameworks!

  pod 'React', :path => '../node_modules/react-native', :subspecs => [
    'Core',
    'CxxBridge',
    'DevSupport',
    'RCTActionSheet',
    'RCTAnimation',
    'RCTBlob',
    'RCTGeolocation',
    'RCTImage',
    'RCTNetwork',
    'RCTSettings',
    'RCTText',
    'RCTVibration',
    'RCTWebSocket',
  ]
  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'
end

気づいた人もいるかと思うが、cocoapods-fix-react-native という gem を使う
cocoapods を使って react-native の依存を解決しようとした時にエラーが出るという issue があり、それを解決してくれるらしい
しかも、RN のバージョンを見てそれにあったパッチを当ててくれるから、たぶんこれを使っておけば間違いない

グローバルに入れたくないので bundler で gem を管理する

$ cat<<EOF > Gemfile
source "https://rubygems.org"

gem "cocoapods-fix-react-native"
EOF
$ bundle install
$ pod install

これで必要なモジュールは全て入ったので、react-native を乗せた ViewController を立ち上げるまでを見ていく

UIViewController の extension として、RN を起動するメソッドを追加しておけば、あとは好きなところで呼び出せば良い

UIViewController+ReactNative.swift
import UIKit
import React

extension UIViewController {
    func launchReactNativeApp(bundleRoot: String = "index", module: String = "rn_integrated_native", initialProps: NSDictionary? = nil) {
        guard let jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: bundleRoot, fallbackResource: nil) else {
            fatalError("Could not find react-native bundle file!")
        }
        
        let rootView = RCTRootView(
            bundleURL: jsCodeLocation,
            moduleName: module,
            initialProperties: initialProps as [NSObject : AnyObject]?
        )
        let vc = UIViewController()
        vc.view = rootView
        self.present(vc, animated: true, completion: nil)
    }
}
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func onPressButton(_ sender: Any) {
        self.launchReactNativeApp()
    }
}

iOS には ATS があるので、localhost を例外に追加する

Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>localhost</key>
            <dict> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>
// ...

以上で、iOS に関しては当初の目的を達成できた。

Android

疲れたので今度書く

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?