Flutter & iOS问题记录 - The application‘s Info.plist does not contain a valid CFBundleShortVersionString

痛定思痛。 2024-05-24 21:43 135阅读 0赞

文章目录

  • 前言
  • 开发环境
  • 问题描述
  • 问题分析
  • 解决方案
  • 补充内容
  • 总结
  • 最后

前言

开发Flutter项目以来,第一次碰到这种奇怪问题,简直怀疑人生。

开发环境

  • Flutter: 3.3.5
  • Dart: 2.18.2
  • Xcode: 14.0.1
  • Android: 2021.3.1 Patch 1

问题描述

同事拉了最新的代码到自己电脑上,修复了一些问题,先在Android设备上运行测试没问题,接着问题来了,在iOS真机上运行时发现应用版本名称获取不到。可是,这个获取应用版本名称功能从实现完到现在就没改动过了。最奇怪的是,我电脑上的同个项目运行在同个iOS真机上是正常的。

问题分析

  1. 代码改动的原因?
    我马上想到这不会是同事自己改代码改出的问题吧,同事马上跳出来反驳我说不可能,我review了下代码,发现这些改动确实不至于引发这个问题。
  2. package_info_plus版本不一致的原因?
    对比pubspec.lock文件中依赖版本,发现确实同事的比较新,去Pub看了下Changelog,也没说iOS获取应用版本名称有什么变化,按我多年iOS/Android的原生开发经验,这插件获取应用版本名称的方式应该不会变。尝试将两边的package_info_plus版本号统一,问题并没有解决。
  3. 开发环境不一致的原因?
    首先检查Flutter版本,两边都升级到最新的3.3.5版本,问题还在。Xcode都升级到最新的14.0.1,问题依旧还在。
  4. Xcode命令行工具的原因?
    执行xcode-select --install命令提示command line tools are already installed,好吧,应该也不是这个问题,删除重装Xcode命令行工具也不行。

经过以上操作,应用版本名称依旧获取不到,Android Studio中的运行日志也没看到报错信息。既然Flutter项目中获取不到,那我用Xcode打开对应的iOS项目,获取应用版本名称打印出来看看。

打印应用版本名称的源码:

  1. print(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "")

运行后打印结果是空的,什么鬼!我又在我电脑上的试了以下是正常的,难道是Info.plist配置不一样?对比两边的配置,一模一样,尝试获取里面的应用版本号,发现是可以的。难道是CFBundleShortVersionString属性的值$(FLUTTER_BUILD_NAME)有问题。找了下FLUTTER_BUILD_NAME定义的地方,如下图:

screenshot1

通过图片可以看出这并没有什么问题,最主要的是,从项目创建到现在CFBundleShortVersionString属性的值就没改过,这是Flutter项目默认的。 这下真的怀疑人生了,我这没问题,同事的有问题,没有报错信息,而且同事之前运行也没问题,要说最大的区别就是升级了Xcode,但是我也升级了。新建了一个Flutter项目,Info.plist中配置应用版本名称的方式也没变。

就在我一筹莫展的时候,同事跟我说在iOS模拟器运行报错了。错误信息是The application's Info.plist does not contain a valid CFBundleShortVersionString,这离了大谱,在项目中的Info.plist肯定是没问题的,那肯定就是打包的时候出问题了。

先找到打包后的Runner.app文件一探究竟,对于Android Studio运行的,Runner.app文件在项目根目录/build/ios/iphonesimulator/这个路径,对于Xcode运行的,可以选中Products下的Runner,右击选择Show in Finder,在新打开的窗口中可以找到Runner.app文件。选中Runner.app显示包内容,找到里面的Info.plist文件并打开,确实少了CFBundleShortVersionString属性。

问题的原因找到了,但没完全找到,这还不能完全解释为什么会出现这个问题。不过,问题分析到这里,我已经想到解决方案了。写解决方案之前,先来说说我在iOS原生项目开发时对于应用版本名称是怎么配置的。

项目打包环境会分开发/预发/正式三种环境,所以会有三个Info.plist文件(文件名称会带上环境名区分),CFBundleShortVersionString属性配置的是$(MARKETING_VERSION)MARKETING_VERSION属性的值其实就是下图所示位置设置的值。

screenshot2

所以,每次版本更新时,只需要在上图所示位置改一下就可以了。从这里可以看出,之所以会出现这个问题,很有可能是Flutter项目打包时,MARKETING_VERSION属性值为空导致Info.plist缺失CFBundleShortVersionString属性。不过这也还不能完全解释为啥我电脑上运行是可以的,毕竟两边项目里面的配置是一样的。

解决方案

首先你需要用Xcode打开项目,如果没在下图所示位置设置过版本名称,请随便设置一个(后面应用版本名称会和FLUTTER_BUILD_NAME的值同步,不会影响到正常的应用版本名称,所以请随意设置),不然MARKETING_VERSION属性可能搜索不到。

screenshot2

然后按下图所示搜索Marketing Version和设置属性值为$(FLUTTER_BUILD_NAME),设置完点击旁边空白处会自动保存。

screenshot3

设置完毕,MARKETING_VERSION属性值自动变成了FLUTTER_BUILD_NAME的值。

screenshot4

这边的应用版本名称也自动同步了。

screenshot5

到此,这个问题就完美解决了。虽然解决方案简单,但是找到解决方案的过程一言难尽。

补充内容

Fastlane打包的ipa包上传fir后不显示应用版本名称,本质还是同一个问题。找到打包上传的ipa文件,将.ipa文件后缀名改为.zip,然后解压缩,找到Payload文件夹里的Runner.app,右击显示包内容找到Info.plist文件打开,会发现一样缺失CFBundleShortVersionString属性。

总结

问题本身很简单,难就难在为什么我电脑上是正常的,运行在iOS真机也没有报错,而且这个配置是Flutter创建项目的时候默认配置的,这个项目都到尾声了突然出现这个问题,真是让人困惑。

最后

如果这篇文章对你有所帮助,请不要吝啬你的点赞?加星?,谢谢~

发表评论

表情:
评论列表 (有 0 条评论,135人围观)

还没有评论,来说两句吧...

相关阅读