Xcode9下打包app,icon不显示问题详解

问题:

升级Xcode9之后,打包app发现icon无法显示。并且审核时会报错,说icon图标缺失。例如:

Missing required icon file. The bundle does not contain an app icon for iPhone/iPod Touch of exactly "120x120" pixels.

解决方案:

  • 1.检查icon是否缺失,项目配置是否正确。
  • 2.icon图片是否正确
  • 3.是否使用Cocoapods(关键)

1.工程icon配置

主要有2个地方:
1)项目TARGETS下:


Xcode9下打包app,icon不显示问题详解_第1张图片
WX20171213-142933.png

2)项目Build Settings下:


Xcode9下打包app,icon不显示问题详解_第2张图片
WX20171213-143054.png

2.icon图片检查

1)Xcode9需要提供1024x1024尺寸的,每个尺寸的图片都严格按照官方要求
2)所有的icon都不能有Alpha通道
3)有的人说直接将其他图片格式的后缀改为.png也会有问题,所以,建议每个icon都用软件提供的导出功能,生成png图。

3.Cocoapods在Xcode9下的问题

目前为止,Cocoapods在Xcode9下存在问题,这里是issue地址:https://github.com/CocoaPods/CocoaPods/issues/7003

提供了2种解决方案:

1)修改pods的脚本文件(不推荐)

找到../Pods/Target Support Files/Pods-[Your Project Name]/Pods-[Your Project Name]-resources.sh文件,替换最后一句命令:

  • 替换前
    printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"

  • 替换后
    printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${BUILD_DIR}/assetcatalog_generated_info.plist"

2)修改podfile(推荐,并了解其原理)

在podfile文末(end之后),加上如下代码:

post_install do |installer|
  # 1
    copy_pods_resources_path = "Pods/Target Support Files/Pods-[Your Project Name]/Pods-[Your Project Name]-resources.sh"
  # 2
    string_to_replace = '--compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"'
  # 3
    assets_compile_with_app_icon_arguments = '--compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${BUILD_DIR}/assetcatalog_generated_info.plist"'
  # 4
    text = File.read(copy_pods_resources_path)
  # 5
    new_contents = text.gsub(string_to_replace, assets_compile_with_app_icon_arguments)
  # 6
    File.open(copy_pods_resources_path, "w") {|file| file.puts new_contents }
end

解读上文内容:
#1 是脚本文件的路径,
#2#3 分别是2个字符串变量,
#4 读取了前面路径的内容,
#5#3的字符串替换#2的字符串,
#6 将改动写入文件
post_install 当我们安装完成,但是生成的工程还没有写入磁盘之时,我们可以指定要执行的操作。我们可以在这个时候对pod的配置做一些修改。这里的修改结果其实和方案一的目的是一样的,但是避免了重复pod install之后,配置被还原的问题。

为什么要这么做?

简单看下resources.sh里面改动的内容做了什么事情,我再粘贴一下这段内容,并做一点点排版。为了方便阅读,还将文件里前面的部分内容粘贴过来了

# 原本的内容
if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
then
 # Find all other xcassets (this unfortunately includes those of path pods and other targets).
 OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
 while read line; do
   if [[ $line != "${PODS_ROOT}*" ]]; then
     XCASSET_FILES+=("$line")
   fi
 done <<<"$OTHER_XCASSETS[]"

# 改动的内容
printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool 
--output-format human-readable-text 
--notices
--warnings 
--platform "${PLATFORM_NAME}" 
--minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" 
${TARGET_DEVICE_ARGS} 
--compress-pngs 
--compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 
--app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" 
--output-partial-info-plist "${BUILD_DIR}/assetcatalog_generated_info.plist

解读改动过的内容:
①printf即打印出${XCASSET_FILES}的内容,这些是项目中的资源文件
xargs -0是linux命令,即做完打印操作之后再做一些事。什么事?
③xcrun 提供了一种从命令行查找或调用开发人员工具的方法,而不需要
用户修改Makefile或者采取不方便的措施来支持多个Xcode工具
链。它找到了actool,编译、打印、更新和修改asset catalogs的工具。(安装xcode之后也可在终端用man查看)
④最后就是查阅actool,看看后面的配置是做什么的。相比之前,其实就是加了--app-icon--output-partial-info-plist2个选项。
--app-icon可以和--compile组合使用,选择一个app icon,这个icon会被拷贝到--compile指定的目录下,或者拷贝到car file中,这取决于--minimum-deployment-target的值。例如:我的项目编译后,看到的--minimum-deployment-target的值是iphone,所以icon应该会被拷贝到--compile指定的目录下。但是,macOS 10.13或者 iOS 11.0 之后的版本,icon都会被拷贝到car file文件下。部分定义的image(不存放在xcassets文件中的image)还是会生成在--compile指定的目录下。官方说这种情况未来可能会被取消。最后,这个flag还会生成一份plist文件。这个plist文件的路径和名称由--output-partial-info-plist决定。这个plist在编译的期间会被merge到项目的Info.plist文件中。我截了个图,大概是下面这个样子。

Xcode9下打包app,icon不显示问题详解_第3张图片
assetcatalog_generated_info.png

简单的归纳一下:就是原本actool会把所有的资源文件找到,然后“输出”到2个地方,car file--compile指定的目录下(在xcassets中的资源输出到car file,零散的资源输出到app包里)。在mac OC 10.13和iOS 11.0之后的版本,icon会被拷贝到car file中(可能苹果希望这么做吧)。但是,我对比了有无--app-icon前后的包,发现icon都在app目录下,并不存在于car file中。还是没有看出有没有这个参数的区别,后续有新发现再更新吧。
Tips:查看app包中car file的方法,个人学习之提取app以及Assets.car包中的素材

最后

简单的说,用了Cocoapods后,Xcode9打包无法发布的问题,修改Podfile文件可以达到目的。
有个小Tips,脚本里面有OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)这样一行命令,这是Cocoapods去查找.xcassets文件的。但是它是基于$PWD目录查找的,打印发现是工程的主目录。我的项目中,.xcassets存放在了别的路径下,所以一直提示找不到AppIcon。望大家注意~还是把它移到主目录下吧

说了这么多,其实离真相还是差一点的。
如果有人知道Cocoapods产生这个问题的根本原因,望指点,谢谢!

你可能感兴趣的:(Xcode9下打包app,icon不显示问题详解)