解决Xcode9打包引起的iOS9图片崩溃问题

本系列博客是本人的开发笔记。为了方便讨论,本人新建了一个微信群(iOS技术讨论群),想要加入的,请添加本人微信:zhujinhui207407,【加我前请备注:iOS 】,本人博客http://www.kyson.cn 也在不停的更新中,欢迎一起讨论

广告

我的首款个人开发的APP壁纸宝贝上线了,欢迎大家下载。

解决Xcode9打包引起的iOS9图片崩溃问题_第1张图片
壁纸宝贝

引言

周一一上班就在Bugly中发现了如下崩溃:

0   libobjc.A.dylib
objc_msgSend + 16
1   CoreFoundation
CFEqual + 340
2   CoreFoundation
___NSCacheKeyEqual + 12
3   libcache.dylib
__entry_get_optionally_checking_collisions + 164
4   libcache.dylib
cache_get_and_retain + 132
5   CoreFoundation
-[NSCache objectForKey:] + 68
6   CoreUI
-[CUIStructuredThemeStore _canGetRenditionWithKey:isFPO:lookForSubstitutions:] + 360
7   CoreUI
-[CUICatalog _resolvedRenditionKeyFromThemeRef:withBaseKey:scaleFactor:deviceIdiom:deviceSubtype:sizeClassHorizontal:sizeClassVertical:memoryClass:graphicsClass:graphicsFallBackOrder:] + 1416
8   CoreUI
-[CUICatalog namedLookupWithName:scaleFactor:deviceIdiom:deviceSubtype:sizeClassHorizontal:sizeClassVertical:] + 148
9   UIKit
___98-[_UIAssetManager imageNamed:scale:idiom:subtype:cachingOptions:sizeClassPair:attachCatalogImage:]_block_invoke + 424
10  UIKit
-[_UIAssetManager imageNamed:scale:idiom:subtype:cachingOptions:sizeClassPair:attachCatalogImage:] + 212
11  UIKit
-[_UIAssetManager imageNamed:withTrait:] + 528
12  UIKit
__UIImageWithNameAndTraitCollection + 96
13  UIKit
+[UIImage(UIImagePrivate) _kitImageNamed:withTrait:] + 36

这个崩溃在只在iOS9上有,并且是图片引起的。于是我们想起了之前的使用Xcode10打包引起崩溃的系列博客:
XCode 10打包上传后在iOS 9上Crash(2018)
our app crashed in iOS 9 which upload by Xcode 10

但我又跟小伙伴确认过,我们是使用Xcode9打包的,按道理不会出现这种情况。于是我们又陷入了迷茫。

分析

直到笔者最近在使用swift写代码的时候才意识到问题:
笔者已经使用习惯了使用ReactiveCocoa,因此在最近使用Swift开发的时候也相应的使用了ReactiveCocoa的swift版ReactiveSwift。但由于Xcode10对ReactiveSwift兼容不是很完善(或者反之ReactiveSwift还没有来得及升级,以适应Swift的新版本),笔者经常会来回切换与Xcode9与10之间。但有的时候发现即使使用Xcode9编译还是编译不过。最后最终在这里找到了解决方案:


解决Xcode9打包引起的iOS9图片崩溃问题_第2张图片
image

也就是说虽然笔者选择了Xcode9进行开发,但其实打包的时候选择的还是Xcode10。
真相终于大白!
最后 我们来回顾一下Xcode10打包会出现这个问题的根本原因,以及出现这件事情的前因后果:

该错误在iOS的开发者网站上是有编号的,即ITMS-90682,按这个关键字搜 Stack Overflow,就能很容易找到如下答案:
How to resolve "ERROR ITMS-90682: Invalid Bundle - The asset catalog at 'Payload/XXXXX/Assets.car' can't contain 16-bit or P3 assets if the app supports iOS 8 or earlier."

With Xcode 8 GM, this error will occur if you include 16-bit or P3 assets in an app submission targeting iOS releases earlier then iOS 9.3. If your app requires wide color functionality you must change your Deployment Target to iOS 9.3 or later. If your app does not require wide color functionality and you wish to deploy it to older iOS versions then you should replace all 16-bit or P3 assets with 8-bit sRGB assets. You can find 16-bit or P3 assets by running “assetutil” on the asset catalog named in the error message from iTunes Connect.

上面的内容笔者就不做过多翻译了,大概的意思就是:
导致这种问题的原因是:在 Xcode 8 中,当你资源文件中[含有16位图]或者[图片显示模式γ值为’P3’]且iOS targets设定为iOS 9.3以下就会出现这个问题. 如果你的app需要支持广色域显示的话,那你必须得把target设置成iOS 9.3+,相反,如果你的app不需要支持广色域且你想兼容 iOS 9.3 之前的项目,你就得把所有的16位的或者显示模式为’P3’图片全都替换成8位模式的sRGB颜色的图片。

但有几个名词大家可能不太明白

  • RGB
  • P3
  • sRGB

这里引用一些文字来描述他们的不同:

sRGB色彩空间是美国的惠普公司和微软公司于1997年共同开发的标准色彩空间(standard Red Green Blue),由于这两家公司的实力强,他们的产品在市场中占有很高的份额。而AdobeRGB色彩空间是由美国以开发Photoshop软件而闻名的 Adobe公司1998年推出的色彩空间标准,它拥有宽广的色彩空间和良好的色彩层次表现,与sRGB色彩空间相比,它还有一个优点:就是Adobe RGB还包含了sRGB所没有完全覆盖的CMYK色彩空间。这使得Adobe RG8色彩空间在印刷等领域具有更明显的优势。
Display P3 是 Apple 在 DCI-P3 基础上参考了 sRGB 而修订出的自己的标准,它拥有 sRGB 的 Gamma 2.2, 而不是 DCI-P3 的 2.6. 同时 White Point 也与 sRGB 同为 D65(6500K),并非 DCI-P3 的 D50(5500K)(说人话就是:DCI-P3 规定的标准白色会比 Display P3 更偏黄一些,且 DisPlay P3 由于更低 Gamma 整体画面风格会更亮一些。)iPhone 7 & 7 Plus 拥有全新的 DCI-P3 色域的屏幕,随着 iPhone 7 & 7 Plus 正式发货,现在已经可以确认新 iPhone 的照片也是以 Display P3 存储的。

综上,需要把P3图片换成sRGB原因在于,iOS9以下不支持广域图片,因此有人写了如下脚本来替换App中的所有p3的图片:

#!/bin/bash
DIRECTORY=$1
echo "------------------------------"
echo "Passed Resources with xcassets folder argument is <$DIRECTORY>"
echo "------------------------------"
echo "Processing asset:"
XSAASSETSD="$(find "$DIRECTORY" -name '*.xcassets')"
for xcasset in $XSAASSETSD
do
    echo "---$xcasset"
    IMAGESETS="$(find "$xcasset" -name '*.imageset')"
    for imageset in $IMAGESETS
    do
        echo "------$imageset"
        FILES="$(find "$imageset" -name '*.png')"
        for file in $FILES 
        do
            echo "---------$file"
            sips -m "/System/Library/Colorsync/Profiles/sRGB Profile.icc" $file --out $file
        done
    done
done
echo "------------------------------"
echo "script successfully finished"
echo "------------------------------"

这个脚本其他部分很好理解,有个命令值得我们研究

sips

这里我们不具体展开讲,仅贴出几个常用的操作示例,更多用法请大家自行研究
自适应裁剪图片
sips -Z 600 meinv.jpg
其中600表示高度为600px,宽度为按比例缩放
固定宽度
sips -z 100 200 meinv.jpg
其中100表示高度为100px,宽度为200px
旋转
sips -r 90 meinv.jpg
向右旋转90度
水平方向/垂直方向翻转图片
sips -f horizontal meinv.jpg
sips -f vertical meinv.jpg

参考

  • 【进阶】当评价一款产品时,我们关注的是什么?(一)我们需要什么样的显示器(屏幕)
  • iPhone 7 的照片是以 Display P3 为色彩空间描述的,这意味着什么?
  • Xcode 8 build crash on iOS 9.2 and below
  • Weird crash on iOS 9.0, 9.1, 9.2
  • mac上使用sips命令快速裁剪、旋转、翻转图片

你可能感兴趣的:(解决Xcode9打包引起的iOS9图片崩溃问题)