返回

Expo Prebuild 生成多个 CFBundleURLSchemes 原因及解决方法

IOS

Expo Prebuild 生成多个 CFBundleURLSchemes,咋回事?

用 Expo 开发 App,配置 scheme 的时候遇到点小麻烦。按官方文档在 app.json 里设置了 scheme: 'myappname'prebuild 之后发现 Info.plist 里面 CFBundleURLSchemes 有重复,心里有点慌,怕以后出问题。

啥原因?

仔细研究了一下,发现这个问题和 Expo 的工作方式,还有咱们配置 app.json 的方式有关。

  • Expo 的自动配置: Expo 为了简化开发流程,会自动帮我们配置很多东西,包括 URL Scheme。它会根据 app.json 里面的 slugname 字段生成一些默认的 Scheme。
  • 咱们的自定义 Scheme: 我们在 app.json 里加的 scheme 字段,又定义了一个 Scheme。
  • iOS 的 Bundle Identifier: iOS 应用的 Bundle Identifier(例如:fi.myappname.app) 也会被包含作为可用的scheme.

这几个因素加起来,就导致 Info.plist 里面出现了多个 CFBundleURLSchemes

咋解决?

目前来看,多个 Scheme 同时存在一般不会直接导致应用崩溃或功能异常。但为了避免潜在问题,也为了代码更干净,可以尝试以下几种方法:

1. 只用 app.json 里的 scheme (推荐)

这是最简单直接的方法。如果 app.json 里已经定义了 scheme,就不用担心 Expo 自动生成的那些。

原理: 明确告诉 Expo 我们要用哪个 Scheme,避免它瞎猜。

操作步骤:

  1. 确保 app.json 里有 scheme 字段:

    {
      "expo": {
        "scheme": "myappname",
        "ios": {
            "bundleIdentifier": "fi.myappname.app"
        },
        ...
      }
    }
    
  2. 重新运行 npx expo prebuild --clean

  3. 检查 ios/[YourProjectName]/Info.plist 文件,确认CFBundleURLSchemes里是你想要的。

额外说明 : 这种方式比较稳妥, 只要你确保app.json 中设置了正确的schemebundleIdentifier

2. 用 Expo Config Plugin 修改 Info.plist

如果想对 Info.plist 做更细致的修改,可以用 Expo Config Plugin。

原理: Config Plugin 允许我们在 prebuild 过程中,用代码修改原生项目的配置。

操作步骤:

  1. 安装 @expo/config-plugins

    npm install @expo/config-plugins
    
  2. 创建一个新的插件文件(例如 plugins/withCustomScheme.js):

    const { withInfoPlist } = require('@expo/config-plugins');
    
    const withCustomScheme = (config) => {
      return withInfoPlist(config, (config) => {
        // 假设我们只想保留 app.json 里定义的 scheme
        const customScheme = config.modRequest.config.scheme;
        config.modResults.CFBundleURLTypes = [
          {
            CFBundleURLSchemes: [customScheme],
          },
        ];
        return config;
      });
    };
    
    module.exports = withCustomScheme;
    
  3. app.json 里使用这个插件:

        {
          "expo": {
            "scheme": "myappname",
                "ios": {
                    "bundleIdentifier": "fi.myappname.app"
                },
            "plugins": [
              "./plugins/withCustomScheme.js"
            ]
          }
        }
    
    
  4. 重新运行 npx expo prebuild --clean

  5. 检查 ios/[YourProjectName]/Info.plist

进阶使用:

Config Plugin 的能力很强,不仅能改 Info.plist,还能改其他原生配置文件。可以根据需要编写更复杂的插件。例如,根据不同环境设置不同的 Scheme。

// plugins/withCustomScheme.js (更复杂的例子)

const { withInfoPlist } = require('@expo/config-plugins');

const withCustomScheme = (config, props) => { // 接受参数
  return withInfoPlist(config, (config) => {
    const customScheme = config.modRequest.config.scheme;
    let schemes = [customScheme];

    if (props.includeBundleId) {
      schemes.push(config.ios.bundleIdentifier);
    }

    config.modResults.CFBundleURLTypes = [
      {
        CFBundleURLSchemes: schemes,
      },
    ];
    return config;
  });
};

module.exports = withCustomScheme;

{
    "expo":{
      "plugins": [
             [
                "./plugins/withCustomScheme.js",
                 {"includeBundleId": true}
             ]
          ]
    }
}

安全建议:

  • 使用 Config Plugin 修改原生配置时要小心,确保了解自己在做什么。
  • 修改前最好备份一下原生项目。

3. 手动修改 Info.plist (不推荐)

可以直接编辑 ios/[YourProjectName]/Info.plist 文件,删除多余的 CFBundleURLSchemes

原理: 直接改最终生成的配置文件。

操作步骤:

  1. 找到 Info.plist 文件。
  2. 找到 CFBundleURLTypes 部分。
  3. 删除不需要的 CFBundleURLSchemes

缺点:

  • 每次 prebuild 之后都要手动修改,很麻烦。
  • 容易出错。
  • 不符合 Expo 的开发理念。

强烈不推荐这种方法

4. 使用 expo-build-properties (针对特定情况)

如果问题是由 expo-build-properties 引起的 (例如,你设置了usesNonExemptEncryption: false), 你可以在 app.json 中进行针对性配置:

原理 : 通过 expo-build-properties 明确地控制某些构建行为。

操作步骤 :

  1. app.json 中添加相关配置:

       "expo": {
           ...
           "plugins": [
              [
                "expo-build-properties",
               {
         "ios": {
             "newArchEnabled": false,
             "useFrameworks": "static"
    
               }
              }
              ]
            ]
        }
    
    

    上面的配置项要根据实际情况来定, 关键是明确控制 expo-build-properties 影响到的方面。

  2. 重新 npx expo prebuild --clean.

  3. 检查Info.plist

进阶使用 :
expo-build-properties 允许很精细地调整构建设置, 但如果配置不当,可能会引入其他问题.所以,要根据错误日志和具体构建报错,逐步排查和调整。

总结:

这几种方法各有优劣。 最推荐的是第一种,直接用 app.json 里的 scheme。如果需要更精细的控制,可以用 Config Plugin。尽量避免手动修改 Info.plist。希望这几种方法能帮你解决问题!