Xcode13 (iOS15 SDK) 対応で UITabBar を修正した際にバッジ表示が崩れた場合の対処法

## 環境

- Xcode 13.0 (13A233)
- iOS 15.0

## 何が起こったのか

Xcode13 (iOS15 SDK) では `UITabBar` に対して、

- 背景色が透過してしまう、適用されない
- タブバー上部のボーダーが表示されない

といった問題が発生するため、 [UITabBar.standardAppearance](https://developer.apple.com/documentation/uikit/uitabbar/3198046-standardappearance) や [UITabBar.scrollEdgeAppearance](https://developer.apple.com/documentation/uikit/uitabbar/3750912-scrolledgeappearance) を設定するといった対応が必要となってきます。

具体的には、以下のようなコードです。

```swift:UITabBar&#x20;の&#x20;Xcode13&#x20;対応
// 元々の実装
UITabBar.appearance().isTranslucent = false
UITabBar.appearance().backgroundColor = .white

// 以下が Xcode13 の追加対応
let appearance = UITabBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = .white

// `standardAppearance` は iOS 13.0+
UITabBar.appearance().standardAppearance = appearance

if #available(iOS 15.0, *) {
  UITabBar.appearance().scrollEdgeAppearance = appearance
}
```

これで十分かと思いきや、 `UITabBarItem` に見た目を変更したバッジを表示してみると

|iOS 14.5|iOS 15.0|
|:-:|:-:|
|![iOS14.5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178830/f5e77a63-9b38-a715-2358-30284caea438.png)|![iOS15.0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178830/e0a027aa-6312-bd82-ac66-d52961c19677.png)|

のように、バッジの見た目がデフォルト設定に戻ってしまう現象が発生してしまいました。

## 対処法

この現象の影響を受けるのは、 [UITabBarItem.badgeColor](https://developer.apple.com/documentation/uikit/uitabbaritem/1648567-badgecolor) や [UITabBarItem.setBadgeTextAttributes(_:for:)](https://developer.apple.com/documentation/uikit/uitabbaritem/1648566-setbadgetextattributes) を利用して、バッジの見た目を変更している場合となります。

```swift:影響を受けるような設定
thirdVC.tabBarItem.badgeColor = .clear
thirdVC.tabBarItem.badgeValue = "●"
thirdVC.tabBarItem.setBadgeTextAttributes([.foregroundColor: UIColor.red], for: .normal)
```

結論から言うと、 タブバーの見た目を変えるために [UITabBarAppearance](https://developer.apple.com/documentation/uikit/uitabbarappearance) が必要なように、タブバーの各タブの見た目を変えるためには [UITabBarItemAppearance](https://developer.apple.com/documentation/uikit/uitabbaritemappearance) の設定が必要なようでした。

最終的な対応としては、以下のようになります。

```swift:バッジ表示を考慮した&#x20;UITabBar&#x20;の&#x20;Xcode13&#x20;対応
// `UITabBarItemAppearance` を用意
let barItemAppearance = UITabBarItemAppearance()
// タブの見た目を `UITabBarItemStateAppearance` を利用して変更
// `.normal`, `.selected`, `.disabled`, `.focused` の4状態があるので、必要に応じて設定
barItemAppearance.normal.badgeBackgroundColor = .clear
barItemAppearance.normal.badgeTextAttributes = [.foregroundColor: UIColor.red]

// `UITabBarAppearance` を用意
let tabBarAppearance = UITabBarAppearance()
tabBarAppearance.configureWithDefaultBackground()
tabBarAppearance.backgroundColor = .white
// 通常のタブバー表示
tabBarAppearance.stackedLayoutAppearance = barItemAppearance
// iPad 端末でのアイコンとラベルが横並びする場合のタブバー表示
tabBarAppearance.inlineLayoutAppearance = barItemAppearance
// iPhone 端末での landscape 表示の場合のタブバー表示 (タブバー縦幅が狭い)
tabBarAppearance.compactInlineLayoutAppearance = barItemAppearance

// 用意した `UITabBarAppearance` を設定
UITabBar.appearance().standardAppearance = tabBarAppearance
if #available(iOS 15.0, *) {
  UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
}
```

確認した限りでは `UITabBar.scrollEdgeAppearance` が設定されていると、今回の現象が発生します。

ただ、`UITabBarItemAppearance` の変更を効かせた `UITabBarAppearance` を `scrollEdgeAppearance` のみに設定した場合には修正が効かず、 `standardAppearance` 側への設定によって修正が効いてくるような動きでした。

## 参考

### `UITabBar` に対する Xcode13 対応

https://shtnkgm.com/blog/2021-08-18-ios15.html#%E3%82%BF%E3%83%95%E3%82%99%E3%83%8F%E3%82%99%E3%83%BC%E3%81%8B%E3%82%99%E9%80%8F%E6%98%8E%E3%81%AB%E3%81%AA%E3%82%8B%E3%80%81%E8%83%8C%E6%99%AF%E8%89%B2%E3%81%8B%E3%82%99%E9%81%A9%E7%94%A8%E3%81%95%E3%82%8C%E3%81%AA%E3%81%84

https://moneyforward.com/engineers_blog/2021/09/22/moneyforward-me-ios15/#post-9355-md-2

### `UITabBarItemAppearance` の設定

https://stackoverflow.com/a/69375126