【iOS 13】アプリアイコンをダークモード対応させることは可能なのか検証してみる!!
はじめに
皆さんはダークモード対応されていますか?
だいぶ対応したアプリが増えてきたように感じます。
対応するのは大変(主に工数が)ですがやっぱり対応したら謎の満足感あります。
私は個人開発のアプリでは対応しましたが,
まだ業務で担当している案件では対応できていないです。
Xcode では,画像や色のアセットでライト/ダークモードで
それぞれ使う色,画像を設定できるのですごく楽ですよね。
アプリアイコンはダークモード対応できないのかな🤔?
と思って調べてみました。
ちなみにアプリアイコンは Xcode にダークモードなどの設定はないですね。
YUMEMI.swift #5 でトークした内容になります。
https://yumemi.connpass.com/event/153206/
アプリアイコンを変更する(iOS 10.3 ~)
アプリアイコンの変更や名前取得などは iOS 10.3 から使えます。
// hogeという名前のアプリアイコンを設定する
if #available(iOS 10.3, *) {
UIApplication.shared.setAlternateIconName("hoge") { error in
if let error = error {
print(error.localizedDescription)
}
}
}
元のアイコンに戻すときは nil をセットすれば良い。
// 元のアイコンに戻す
if #available(iOS 10.3, *) {
UIApplication.shared.setAlternateIconName(nil) { error in
if let error = error {
print(error.localizedDescription)
}
}
}
注意点として下記があります。
-
info.plist
に利用するアイコン情報を記載する -
ViewController
に記載する - メインスレッドで実行する
- 変更するアプリアイコンは
xcassets
を利用せず直接導入する
これらのコードとライト/ダークモードが切り替わった際に呼ばれる,
メソッドを override
して,Appearance が切り替わった際に
それぞれのモードに対応したアプリアイコンを変更させようとしてみます。
実装
実装環境
- Xcode 11.2.1
- macOS Catalina 10.15.1
- iOS 13 and later
サンプルコードは GitHub に用意しました。
必要に応じて参照ください。
https://github.com/MilanistaDev/AppIconCorrespondingToDarkMode
本実装
ライトモードで設定するアプリアイコン画像をセット
ライトモードで設定するアプリアイコンを xcassets
の AppIcon で設定します。
いわゆるいつものアプリアイコンセット作業です。
ダークモードで設定するアプリアイコン画像を準備
ダークモード用アプリアイコンの画像を用意します。
@2x
,@3x
でそれぞれ 120x120,180x180 ピクセルです。
名前は AppIcon-Dark としました。
用意した画像をプロジェクトに追加
先にあった通り Assets.xcassets
で AppIcon を追加しても
ダークモード用の設定ができません。
なので直接プロジェクトに追加します。
info.plist を編集
追加した画像を利用するために info.plist
を編集する必要があります。
下記コードを追加します。
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>AppIcon-Dark</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon-Dark</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
</dict>
見やすいプロパティリストで見ると下記のようになります。
Primary Icon の方がライトモードのアプリアイコン設定で,
黄色の四角の部分が追加したダークモード用アプリアイコン画像のファイル名です。
ライト/ダークモードの設定でアプリアイコンを切り替える
ViewController
でアプリアイコンを変更するコードを書く必要があるので,
例えば ViewController.swift
に下記のようなコードを書きます。
このコードで Appearance が変更された際に,
現在のモードを判別してアプリのアイコンを切り替える処理が実行されます。
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if self.traitCollection.userInterfaceStyle == .dark {
// ダークモード用のアプリを設定する
UIApplication.shared.setAlternateIconName("AppIcon-Dark") { error in
if let error = error {
print(error.localizedDescription)
}
}
} else {
// nilをセットしデフォルトのアプリアイコン画像に変更
UIApplication.shared.setAlternateIconName(nil) { error in
if let error = error {
print(error.localizedDescription)
}
}
}
}
が,しかし・・・
コントロールセンターでライト/ダークモードを切り替えると
エラー出力部分を通過することがわかります。
エラー内容は下記です。
The operation was cancelled.
いろいろ調べて遅延実行するとうまくいくとのことで
下記コードで包んであげると・・・
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
}
ブレイクポイント止めるとライト/ダークモード切り替え時に,
ちゃんとアプリアイコン変更ダイアログが表示されます。
しかし,ブレイクポイントを貼らなければ状況は変わりませんでした。
ライト->ダーク | ダーク->ライト |
---|---|
結果
ライトモードとダークモードの変更時にアプリアイコンを変更することはできなさそう。
この変更がユーザのアプリ内でのアクションではなく,
アプリ外の操作(iOSによるもの)のため,おそらくキャンセルされてしまうのかなと考えました。
(ユーザが起こしているアクションには違いないのですが😅)
では,ユーザが起こす,アプリ内のトリガーで今のモードを判別して,
アプリアイコン画像をセットする処理を書くとちゃんと設定できるのかな?
ユーザが選択可能にする
というわけで,よくある仮の設定画面を用意し,
アプリアイコン画像を現在の Appearance に合わせる,的な
処理を書いてみます。
仮の設定画面はこんな感じで適当に準備しました。
最初のセクションの2番目のセルをタップして
アプリアイコン画像を変える処理を書いてみます。
ライトモード | ダークモード |
---|---|
UITableView
の delegate メソッドのコード。
extension SettingsViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.deselectRow(at: indexPath, animated: true)
if indexPath.section == 0 && indexPath.row == 1 {
// セルがタップされた際にアプリアイコン画像を変更
self.matchAppIcon()
}
}
}
現在の Appearance の状態によってライトモード,ダークモード用の
アプリアイコン画像を設定するコードはこんな感じで書いてみました。
/// Match the App Icon to the current Appearance
private func matchAppIcon() {
if self.traitCollection.userInterfaceStyle == .dark {
// ダークモード用のアプリを設定する
UIApplication.shared.setAlternateIconName("AppIcon-Dark") { error in
if let error = error {
print(error.localizedDescription)
}
}
} else {
// nilをセットしデフォルトのアプリアイコン画像に変更
UIApplication.shared.setAlternateIconName(nil) { error in
if let error = error {
print(error.localizedDescription)
}
}
}
}
セルをタップしてみたところ,ダイアログが表示され,
アプリアイコン画像を変更することができました。
ライトモード | ダークモード |
---|---|
実際の動きは下記のようになります。
ライトモード,ダークモードに切り替わった際にはアプリアイコンはそのまま,
セルのタップをした際に初めてダイアログが出てアプリアイコンが変更されるという感じです。
ライト=>ダーク | ダーク=>ライト |
---|---|
おわりに
コントロールセンターなどでライトモード,ダークモードを切り替える際に
それぞれのモードに対応したアプリアイコン画像を変更することはできないっぽい。
セルのタップやボタンタップなどユーザが起こすアクションをトリガーとすると,
変更した旨のダイアログが出て,各モードに対応したアプリアイコンに変更することは可能でした。
ライトモード,ダークモード切り替え時にアプリアイコン変更できるぜ,
もっとこうした方がクレバーですよー等ありましたらご教示いただければ幸いです。
ご覧いただきありがとうございました!
Author And Source
この問題について(【iOS 13】アプリアイコンをダークモード対応させることは可能なのか検証してみる!!), 我々は、より多くの情報をここで見つけました https://qiita.com/MilanistaDev/items/bea3e1b4ef33e8dd0f9e著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .