Any Appearance :
Use the Any Appearance variant to specify the color value to use on older systems that do not support Dark Mode. 为了适配不支持黑暗模式的系统版本
Light Appearance : 白色模式
Dark Appearance : 黑色模式
颜色
方案一
通过Assets catalog,指定各种模式下颜色的设定。

//改方法会从主功能的Assets.xcassets根据当前环境(DarkMode,LightMode)获取Color对应的颜色
let aColor = UIColor(named: "Color")
//该方法会从指定bundle中的.xcassets文件中获取颜色,traitCollection为当前的特征集合,其中包含了当前的颜色模式。
let color = UIColor(named: "Color", in: Bundle.currentBundle, compatibleWith: traitCollection)
图片
方案一
通过Assets catalog,指定各种模式下颜色的设定。
与颜色的配置一致

//该方法会从主功能的Assets.xcassets根据当前环境(DarkMode,LightMode)获取Color对应的颜色
let anImage = UIImage(named: "Image")
//该方法会从指定bundle中的.xcassets文件中获取图片,traitCollection为当前的特征集合,其中包含了当前的颜色模式。
let anImage = UIImage(named: "Image", in: Bundle.currentBundle, compatibleWith: traitCollection)
方案二:(iOS13 Only)
Symbol Images是基于矢量的图片格式

有以下优点:
- 缩放时不会产生失真
- 可以自行进行染色
- 具有baseline信息,可以以文字的形式出现。
- 可以用字体相关样式信息配置,使它们看起来好像他们属于该字体。
渲染
以上方式可以解决大部分问题。但是某些情况下满足不了需求,比如通过drawRect:
绘制的视图,CALayer
的相关配置。不用担心,你想到的苹果都想到了。下面列出了,当视图模式(UIUserInterfaceStyle
)变化时回调的方法。override这些方法,进行对应环境的适配即可。获取当前模式 可以通过 self.traitCollection.userInterfaceStyle获取即可。
-
UIView
-traitCollectionDidChange:
-layoutSubviews
-drawRect:
-updateConstraints
-tintColorDidChange -
UIViewController
-traitCollectionDidChange:
-updateViewConstraints
-viewWillLayoutSubviews
-viewDidLayoutSubviews -
UIPresentationController
-traitCollectionDidChange:
-containerViewWillLayoutSubviews
-containerViewDidLayoutSubviews
补充说明:
traitCollection 是在 UITraitEnvironment 协议中的属性。该属性由UIScreen,UIWindow,UIView,UIViewController,UIPresentationController实现。
traitCollection属性包含许多交互界面相关环境的配置,DarkMode就属于他的一部分(UIUserInterfaceStyle)。其他配置不在本文讨论。
UIUserInterfaceStyle包含light、dark、unspecified
Asset catalog打包
那么问题来了,想把Assets catalog 打包进framework怎么办?通常我们想在framework中打包资源一般会把所有资源文件先打包成Bundle文件,再把Bundle文件放到framework中。你可能会把.xcassets文件直接放进Bundle文件里。这样当然是不行的。
你可以新建一个iOS项目进行build,然后查看build日志,可以看到如下日志:

XCode会将.xcassets进行编译,具体怎么编译,还没深入研究。
XCode不止编译代码,还会编译一些资源,如xib,coredata相关等等。但是Bundle文件不会进行编译。所以直接将.xcassets 放入Bundle文件中是不会参与编译的。那怎么办?
很简单!
- 在framework工程中建立Bundle的target,注意是target不是Bundle文件。
- 将.xcassets放到这个新建的target中。
- 为framework的target添加bundle依赖。
搞定!
以下是具体步骤:
- 点我下载xcode插件
-
在终端执行以下命令:
cd ~/Downloads unzip iOS_bundle_template.zip
mkdir -p ~/Library/Developer/Xcode/Templates/Custom
mv "iOS Resources Bundle.xctemplate" ~/Library/Developer/Xcode/Templates/Custom -
新建Bundle target

-
为Test添加TestBundle依赖

-
build 一下 framework 你会发现 Products文件夹下回出现TestBundle文件。

-
进入文件夹看看.xcassets文件编译成什么了

原来.xcassets编译成了.car -
使用资源
//将TestBundle 传入 即可 let anImage = UIImage(named: "Image", in: TestBundle, compatibleWith: traitCollection)
搞定!!
Demo在这里
参考文献:
Unleashing the power of asset catalogs and bundles on iOS
Apple Develop document