前言
其实官方文档《Integration with Existing Apps》讲得挺详细,但是有点面向 ios 开发,对于 ios 开发的同学应该很容易看懂吧。不熟悉的我摸索了很久,记录一下。
重要!!!
先参考官网《Setting up the development environment》把 react-native 的开发环境搭建起来,因为基本如出一辙。对于 ios 而言, react-native 像是它的一部分子应用,本质上还是原生应用。
因为就是要用到原生的东西,所以不要用 Expo 这种方式。这个是方便开发用的,最后应该要回到原生来。
能成功启动 react-native,想必也搞定了 CocoaPods 这个麻烦的工具,用来下载原生相关依赖的。
创建 ios app
Xcode Version 14.3 (14E222b)
1、创建一个 ios app
2、填写相关信息
Product Name:顾名思义,这个应用的名字,随便填,自己记住。
Team:没有就先跳过,苹果开发要求的,上线要用到。
Organization Identifier:组织标识,公司或者产品网址倒着写,随便填。
Interface:有 SwiftUI 和 Storyboard 可选,选择 Storyboard。
Language:选 Swift 或 Objective-C 都可以。
3、操作 xcode
上图为例
先点击中间的“分屏按钮”,编辑器就会变成两个编辑区,一个打开 ViewController.m
文件,一个打开 Main
文件。虽然显示是 Main 文件,但硬盘上可以看到是叫 Main.storyboard
文件。
然后点击右边的“组件库按钮”,打开组件库,拖拽一个 button 组件到 storyboard 编辑区,也就是生成一个按钮到应用上。
最后点击左边的“运行按钮”,看到弹出来的手机模拟器上有自己加的 button 就算成功了。
ios 集成 react-native
1、创建一个 react-native app
成功启动后。
- 进入 ios 文件夹,把除
Podfile
文件之外的东西全删了。 - 然后把刚刚新建的 ios 工程里的所有文件放进这个 react-native 的 ios 文件里,接着把刚仅剩下的 Podfile 文件里,原 react-native 应用的名字全部替换成刚刚拷贝过来的这个 ios 的应用名
- 包括测试相关的 “xxxxxTests” 也要替换。当然如果创建 ios 工程没有勾上测试要求,就要把相关的 “xxxxxTests” 去掉。
然后在这个 ios 路径执行:
pod install
这就是 CocoaPods 这个工具在安装 react-native 所需要的原生依赖。当然也不一定要新建一份 react-native 工程。说白了这个 ios 文件夹里的东西就是 ios 原生 app 的东西,创建 ios 应用本身是没有 Podfile 这份文件的。可以执行
pod init
来生成 Podfile 文件。但是要安装运行 react-native 相关的依赖,所以最好是从一份 react-native 工程里把 Podfile 内容拷贝过来,然后执行安装。这也是官网推荐的方法。
2、运行集成了 react-native 的 ios
双击 ios 文件夹里的 .xcworkspace
文件,就会用 Xcode 打开这个 ios 工程。接着刚刚的分屏操作,把编辑器分成两个编辑区。然后根据刚刚创建 ios 应用选择的 Swift 或 Objective-C,根据官网 event-handler 给出的事件代码,添加到 ViewController.m
文件里。
注意:
- 在文件最上面需要添加依赖代码,Swift 添加的依赖是
import React
,Objective-C 添加的#import <React/RCTRootView.h>
。 - 然后代码里
moduleName
这个参数的相关值要替换成 react-native 的应用名。也就是要和入口里的注册函数 AppRegistry.registerComponent(appName, () => App); 里的那个 appName 的值要一致。因为这就是告诉 ios app 加载这个名字的组件。
然后在 Xcode storyboard 编辑区,按住鼠标右键或者 ctrl + 鼠标左键,从视图的 button 组件可以拖出一条蓝线,可以直接指向另外编辑区的刚刚新增的事件函数,这样子视图层的这个按钮就会和逻辑层的响应事件关联起来。
此时再鼠标右键或者 ctrl + 鼠标左键单击 storyboard 上 button 组件,可以看出已经和相应事件绑定了起来。
在 react-native 工程根目录,执行 react-native start
也就是 yarn start 启动 react-native 服务器,会以服务器的方式提供 jsbundle 文件,也就是事件代码里的 8081 index.bundle?platform=ios
地址,可以把这个地址丢到浏览器查看,能看到 js 文件内容,就是生成成功。除去资源文件,其实最终 react-native 产出就是这份 js 文件,然后交到原生端去解析,变成原生组件。
好了,响应代码加了,适配了,绑定了,点击“运行按钮”也就是那个三角形按钮。模拟器跑起来,然后点击一开始就添加的按钮,就能看到 react-native 的界面弹出来了。成功!
3、集成的展示方式
(1) 抽屉式展示改成嵌入式展示
上面代码是类似弹出一个抽屉一样的交互,可以注释掉相关代码,改成以下代码,变成嵌入效果,同时设置嵌入框大小。
CGRectMake 四个参数分别是:x y width height
- Objective-C:
// UIViewController *vc = [[UIViewController alloc] init];
// vc.view = rootView;
// [self presentViewController:vc animated:YES completion:nil];
rootView.frame = CGRectMake(0, 0, 200, 200);
[self.view addSubview:rootView];
- Swift:
// let vc = UIViewController()
// vc.view = rootView
// self.present(vc, animated: true, completion: nil)
rootView.frame = CGRectMake(50, 200, 300, 400);
view.addSubview(rootView)
(2) 点击触发加载改成自动加载
当然不是一定要有个按钮触发,只是方便调试而已。成功之后,可以把相关的 react-native 加载代码放到 viewDidLoad
这个生命周期里,让它自动展示出来。
- (void)viewDidLoad {
[super viewDidLoad];
// react-native 加载代码
}
异常情况
1
如果报错 [RNIntegrade Swift.AppDelegate window]: unrecognized selector sent to instance xxxxxx"
,参考 issue 或者 stackoverflow 给的解决方案。大概意思就是新版本 window 这个对象什么的没有注入要主动声明啥的,可能是可能不是,不太懂。
- Objective-C,在
AppDelegate.h
文件添加相关代码:
// #import <UIKit/UIKit.h>
// @interface AppDelegate : UIResponder <UIApplicationDelegate>
// @end
// 替换成下面这样
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
@property (nonatomic, strong) UIWindow *window;
@end
- Swift,在
AppDelegate.swift
文件添加相关代码:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window:UIWindow? // 添加这一句,问号要带上
...
}
2
在语言选择 Swift 时,如果在 bundleURL: jsCodeLocation,
这一行报出下列的错误:Value of optional type 'URL?' must be unwrapped to a value of type 'URL'
。改动两行代码:
let jsCodeLocation = NSURL(string: "http://localhost:8081/index.bundle?platform=ios");
let rootView = RCTRootView(
bundleURL: jsCodeLocation! as URL,
...,
)
3
上面的修改集成展示方式,可能会报错:UIViewControllerBasedStatusBarAppearance key in the info.plist is set to no
。
在 Xcode 最左边的文件目录选择 info
文件,如图如提示设置参数。当然只是解决了这个报错,实际会有啥影响就不懂了。
剩余问题
在一开始的 Interface 选择的时候,选择 Storyboard
。其实一开始我选择的是 SwiftUI,然后看网上的教程和官网的示例都是 Storyboard 的,就是关键的那一步事件绑定怎么也看不懂按不出来怎么操作。SwiftUI 里的事件绑定方式都不一样,而且工程目录也不一样,都找不到对应文件。尝试了很多次都不行,后面换成 Storyboard 才成功。
这个对熟悉 ios 开发的同学来看应该就很简单吧。后面有知道怎么弄了再更新。
其它
关于 react-native 开发相关,可以参考《react-native ios 流水账》。
与 android 的集成,可以参考《android 原生应用集成 react-native》。