Skip to main content

难点:版本不一致导致module包找不到

下面是一份可直接用于面试的整理,按 背景 → 现象 → 根因 → 排查 → 解决 → 收获 组织,并附 30 秒 / 2 分钟 口述版。


一、项目背景(一句话)

React Native + Expo 钱包 App 里接入自研本地模块 expo-mpc-stack(Rust FFI → libmpc_ffi.xcframework + Swift Expo Module),通过 CocoaPods 与 use_expo_modules! 自动链接进 iOS 工程。


二、难点描述(面试开场)

自定义 Native Module 在 pod install 后“像没装上”ExpoMpcStack 在 Pods 里找不到,或 JS 侧 requireNativeModule('ExpoMpcStack')Native module cannot be null

表象是「module 包找不到」,本质是 iOS 最低部署版本在多处声明不一致,CocoaPods / Expo autolinking 在解析阶段把 Pod 跳过或解析失败,而不是 Swift 代码写错。


三、涉及的多处版本配置(必背)

iOS 最低版本至少要在这些地方 一致(你们项目最终统一到 16.0):

位置作用
modules/expo-mpc-stack/ios/ExpoMpcStack.podspecs.platforms[:ios]Pod 声明的最低 iOS
ios/Podfileplatform :ios, ...整个 Pod 工程的 platform
ios/Podfile.properties.jsonios.deploymentTargetExpo 预构建写入 Podfile 的值
app.jsonexpo.ios.deploymentTargetExpo 配置源,影响 prebuild
Xcode Target → IPHONEOS_DEPLOYMENT_TARGET主 App 编译目标
libmpc_ffi.xcframework 构建时的 min iOS二进制自带的最低系统

你们仓库里关键片段:

s.platforms = {
:ios => '16.0'
}
platform :ios, podfile_properties['ios.deploymentTarget'] || '15.1'
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.phemex.warmwallet",
"deploymentTarget": "16.0"

坑点:Podfile 有 || '15.1' 兜底。若 Podfile.properties.json 未生成、被删、或未跑 expo prebuild,工程 platform 可能是 15.1,而 ExpoMpcStack 要求 16.0 → 版本约束冲突。


四、根因(面试里要说清机制)

  1. CocoaPods 的 platform 是全局约束
    platform :ios, '15.1' 表示「本工程面向 iOS 15.1+」。子 Pod 若声明 platforms => { :ios => '16.0' },resolver 会认为 当前工程 platform 低于 Pod 要求,可能安装失败、被跳过,或后续链接/运行时才暴露问题。

  2. Expo autolinking 依赖 podspec + 工程 platform
    use_expo_modules! 会扫描 modules/*/ios/*.podspec。platform 不一致时,容易出现 Podfile.lock 里没有 ExpoMpcStack,但开发者只盯着 Swift/JS,误以为「包路径错了」。

  3. 和「找不到文件」不是同一类问题

    • 版本不一致 → Pod 根本没进依赖图
    • Xcode 不显示新文件 → 往往是 .xcodeproj 导航树未刷新(Cursor 建文件 vs Xcode 工程树),但 source_files glob 仍可能参与编译

    你们当时要把这两类问题分开记,避免 Clean / 删 DerivedData 打一圈无效操作。

  4. xcframework 还有第三层版本
    Rust 编出来的 framework 若 min OS 高于 App deployment target,会在 link 或运行时再炸一层,所以 podspec、Podfile、xcframework 要一起对齐


五、排查步骤(体现工程能力)

面试可这样说「我按链路从外到内查」:

  1. 确认 Pod 是否被装上

    cd ios && pod install
    grep -i ExpoMpcStack Podfile.lock
    # 或
    pod list | grep -i ExpoMpcStack
  2. 对比三处版本

    • ExpoMpcStack.podspec16.0
    • Podfile 第一行 platform :ios
    • Podfile.properties.json / app.json
  3. 看 autolinking 是否扫到模块

    npx expo-modules-autolinking resolve --platform ios

    确认 expo-mpc-stack 在列表里。

  4. 改版本后的标准动作

    • app.jsonnpx expo prebuild(或只改 Podfile.properties.json
    • cd ios && pod install
    • Xcode Clean Build Folder
  5. 验证运行时

    • Podfile.lockExpoMpcStack
    • 真机/模拟器 iOS ≥ 16
    • JS:requireNativeModule('ExpoMpcStack') 非 null

六、解决方案(结论句)

把所有 iOS 最低版本统一到 16.0,并去掉「一半 15.1、一半 16.0」的状态:

  • app.jsondeploymentTarget: "16.0"
  • ios/Podfile.properties.json"ios.deploymentTarget": "16.0"
  • 各本地 module 的 .podspec:ios => '16.0'ExpoMpc, ExpoAge, ExpoWalletCore 等同策略)
  • 重新 pod install,确认 Podfile.lockExpoMpcStack

业务原因:模块依赖 Passkeys / 新 API、Rust FFI 按 iOS 16 构建,本来就要 16,不能留在 RN 默认 15.1。


七、STAR 口述模板

维度内容
SExpo 钱包接入 MPC 签名本地模块 expo-mpc-stack
T完成 iOS 集成,保证 pod install 后 Native Module 可用
A对比 podspec / Podfile / app.json / Podfile.lock;用 autolinking 命令验证;统一 deployment target;重建 Pods
RExpoMpcStack 进入依赖图,MPC 签名链路在 iOS 16+ 设备跑通;形成「多源版本配置 checklist」

八、面试口述稿

30 秒版

做 Expo 自定义 Native Module 时,ExpoMpcStackpod install 后像没装上。根因不是路径错,而是 podspec 要求 iOS 16,Podfile 兜底还是 15.1,CocoaPods platform 不一致导致 Pod 没进依赖图。我把 app.jsonPodfile.properties.json 和所有本地 podspec 统一到 16.0,重装 Pods 后模块就链上了。

2 分钟版(可追问)

我们在 React Native + Expo 里接了一个带 Rust xcframework 的 MPC 模块。JS 报 Native module 找不到,一开始怀疑是 modules/expo-mpc-stack 路径或 autolinking 配置。

我查了 Podfile.lock,发现根本没有 ExpoMpcStack。对比后发现三处版本分裂:ExpoMpcStack.podspec 写的是 iOS 16,Expo/RN 的 PodfilePodfile.properties.json 读 deployment target,读不到就 fallback 15.1。CocoaPods 的全局 platform 必须 ≥ 各 Pod 的 platforms,否则 resolver 不会正常纳入该 Pod。

处理上我们把 app.jsonPodfile.properties.json、相关 podspec 全部对齐到 16.0,再 prebuild + pod install,用 autolinking resolve 和 Podfile.lock 双重确认。另外我们区分了另一类问题:Cursor 新建 Swift 文件 Xcode 导航不显示,但 glob 的 source_files 仍可能参与编译,避免无效 Clean。

收获是:自定义 Native Module 集成,第一件事是拉齐 deployment target 清单,比改业务代码更重要。


九、可能的追问 & 简答

追问简答
为什么选 16 不跟 RN 默认 15.1?Passkeys、部分 Security API、Rust FFI 构建目标都是 16;业务可接受则全项目抬高,避免混用。
怎么证明是 platform 问题不是代码问题?Podfile.lock 无该 Pod → 依赖解析阶段就失败;有 Pod 再查 link / requireNativeModule
pod install 成功但模块仍 null?看是否 Dev Client 未重编、是否旧 App 缓存、模拟器系统版本是否 < 16。
Expo 正确工作流?app.json → prebuild 更新 ios/pod install;不要只改一端。

十、可写在简历里的一行(英文)

Resolved iOS native module integration failure for custom Expo MPC module by aligning CocoaPods platform, Expo deploymentTarget, and podspec minimum iOS versions (15.1 → 16.0), restoring autolinking and ExpoMpcStack in Podfile.lock.


如果你希望,我可以再压一版 「面试官追问:和 Android minSdk 类比」「画一张配置关系 mermaid 图」 方便你背。