《React Native 精解与实战》书籍连载「iOS 平台与 React Native 混合开发」
此文是我的出版书籍《React Native 精解与实战》连载分享此书由机械工业出版社出版书中详解了 React Native 框架底层原理、React Native 组件布局、组件与 API 的介绍与代码实战以及 React Native 与 iOS、Android 平台的混合开发底层原理讲解与代码实战演示精选了大量实例代码方便读者快速学习。书籍配套视频教程「80 节实战课精通 React Native 开发」此视频课程建议配合书籍学习书籍中原理性的东西讲解的比较清晰而视频教程对于组件、API 等部分的代码实战开发讲解比较直观。书籍所有相关资料请访问http://rn.parryqiu.com之前连载文章列表「80节实战课精通 React Native 开发」视频课程大纲React 与 React Native 简介React Native 底层原理Node.js 简介与 React Native 开发环境配置React Native 中的生命周期React Native 网络请求与列表绑定配置 iOS 与 Android 开发环境本章将详细讲解在 React Native 框架下iOS 平台混合开发的原理以及详细实现方法并依然通过案例进行实际应用学习。本章需要具备 iOS 平台开发语言 Objective-C 或 Swift 以及 iOS 核心类库的基本知识。11.1 iOS 平台混合开发简介当我们需要使用一些 iOS 平台的 API而 React Native 框架目前还没有提供对应的 JavaScript API 时我们就需要自己编写 React Native 框架与 iOS 平台结合的混合开发代码使得 React Native 框架可以直接与 iOS 平台的原生代码进行通信。混合开发的其他使用场景还包括对一些现有的 Objective-C、Swift 或者 C 代码进行复用或者编写一些用于图片处理、数据库或一些其他高级特性的高性能或多线程的代码。React Native 都开放了对应的接口供开发者调用。接下来在原理讲解的章节我们通过结合一个简单的实例详细讲解一下 React Native 中与 iOS 平台混合开发的通信机制这部分内容稍显复杂可能需要反复阅读理解其底层原理并结合小实例进行体会学习在第二部分还将有一个真实的混合开发示例继续加深你对混合开发的理解。这部分内容属于 React Native 开发的高阶内容即使不掌握也不影响你在学习了 React Native 基础知识后进行 App 的开发不过理解并掌握了这部分的话更加有助于你理解 React Native 的底层原理与实现。11.2 iOS 平台混合开发原理详解这一章节我们通过实现在 React Native 框架中调用我们在 Objective-C 中编写的原生代码Objective-C 中的函数返回了一个简单的字符串React Native 框架中通过 JavaScript 代码将字符串获取到在 View 中的 Text 组件上显示。功能虽然简单但是我们主要是通过此简单功能的实现流程深入学习 React Native 中与 iOS 平台结合的混合开发原理。iOS 平台混合开发实现的过程包括如下几个过程在 iOS 平台的原生代码中定义混合开发的入口用于与 React Native 中的 JavaScript 代码进行通信设置 iOS 平台下项目的编译必备设置在 React Native 项目中通过 JavaScript 代码调用混合开发实现的 iOS 平台原生功能。完整代码在本书配套源码的 11-02 文件夹。11.2.1 iOS 原生代码实现原生模块使用 Objective-C 的类定义来实现与 React Native 框架通信的协议接口 RCTBridgeModule注意 RCT 是 ReaCT 取的几个大写字母的缩写。首先我们通过 React Native CLI 命令初始化一个空的项目命令执行如图 11-1 所示。图 11-1 初始化一个空项目使用 Xcode 打开 ios 文件夹下的 xcodeproj 项目文件后续的混合开发我们将在 Xcode 中进行。我们将我们混合开发的模块命名为 MyModule并在 Xcode 中分别建立两个对应的文件一个为头文件 MyModule.h另一个为使用 Objective-C 来实现的类 MyModule.m。建立时可以在 Xcode 新建窗口中选择文件类型如图 11-2 所示。图 11-2 Xcode 下新建文件选择类型头文件 MyModule.m 文件中初始化的代码使用如下代码。1.#importRCTBridgeModule.h2.3.interfaceMyModule:NSObjectRCTBridgeModule4.5.end代码第一行导入了 React Native 框架与原生代码通信的协议头文件 RCTBridgeModule.h。为了通过类对 RCTBridgeModule.h 的实现类中还需要包含 RCT_EXPORT_MODULE() 的宏定义RCT_EXPORT_MODULE() 中还可以传入参数命名自定义原生组件的名称如我们之前定义的文件名为 MyModule这里可以通过传递参数重新定义模块名称RCT_EXPORT_MODULE(RenameMyModule) 这样就将导出的模块命名成了 RenameMyModule。如果不传递参数那么就使用类文件的名称即 MyModule.m 的名称 MyModule。如果模块类文件包含 RCT 开头的文件名那么最终的模块名称将自动不包含 RCT 字符串。MyModule.m 文件中的代码实现如下。1.#importMyModule.h2.3.implementationMyModule4.5.// 需要包含的宏定义6.RCT_EXPORT_MODULE()7.8.// 定义了一个返回的字符串9.-(NSDictionary*)constantsToExport{10.return{hello:你好这是我编写的第一个 iOS 原生模块};11.}12.13.// 定义了一个可被调用的函数14.RCT_EXPORT_METHOD(squareMe:(NSString*)number:(RCTResponseSenderBlock)callback){15.intnum[number intValue];16.callback([[NSNull null],[NSNumber numberWithInt:(num*num)]]);17.}18.19.end此段代码定义了一个固定的字符串输出方法为 constantsToExport返回了名称为 hello 的字符串。第二个定义了一个可以供 React Native 的 JavaScript 代码调用的函数函数功能非常简单就是将传递过来的 int 参数进行平方计算计算后将计算的值返回。函数的定义需要使用宏命令 RCT_EXPORT_METHOD 进行显式地定义。定义的函数都会被异步地调用所以函数的定义不是直接使用 return 返回一个值和固定的字符串返回不一样。squareMe 是定义了此函数的函数名称参数为一个 NSString 型的值名称为 number另一个参数为函数的回调函数用于获取原生代码的执行结果。函数的 callback 第一个参数为错误的返回这里没有错误就返回了一个 null第二个为计算后的值供函数回调使用。11.2.2 iOS 项目编译设置如上代码都编写完成后在 Xcode 中执行项目编译点击 Xcode 中的 Build 命令如图 11-3 所示。图 11-3 Xcode 项目的编译如果在编译时遇到 fatal error: ‘RCTBridgeModule.h’ file not found 的错误即 RCTBridgeModule.h 文件找不到的问题错误如图 11-4 所示。图 11-4 RCTBridgeModule.h 文件找不到的错误解决的方法为在 Xcode 的项目设置“Build Settings”选项卡下找到“Header Search Paths”设置节点并确认在其中包含了如图 11-5 所示的定义即添加了 $(SRCROOT)/…/node_modules/react-native/React 值的定义并在下拉选项中选择了“recursive”。图 11-5 设置 Xcode 的 Search Paths进行了如上的设置后再次编译项目即可解决此错误问题。