はじめに
歴史のあるiOSアプリのプロジェクトになると、Swift移行が完全でなくObjective-C(以降、objc)のコードが残存していたりするかと思います。
自分の関わるプロジェクトでは、ダークモード対応するぞ!ってなったときに、objcのコードが残っていたので一部objcで対応しました。
コードから直接カラーセットを利用する
Storyboard上のパーツにカラー指定すれば基本的には対応できますが、中にはコード上でカスタムカラーを指定している場合もあります。
Swiftで記述する場合はenum
でカラーセットを定義してそれを利用するとか、UIColor
のextensionでカスタムカラーを定義する方法があるかと思います。
自分の関わったプロジェクトでは前者の方法で対応していたため、objcでenumを使えませんでした。
objc用で列挙型を定義するのもありかもしれませんが、いずれobjcを撲滅することを考えるとわざわざ定義するのに工数もかけたくありません。
直接呼び出せればいいやって感じです。
その時は以下のようにします。
// ラベルの文字色を決めるとき
textLabel.textColor = [UIColor colorNamed: @"hogehoge"];
// 画像の枠の色を決めるとき
imageView.layer.borderColor = [[UIColor colorNamed: @"hugahuga"] CGColor];
一応、Swiftだとこんな感じになります。
// ラベルの文字色を決めるとき
textLabel.textColor = UIColor(named: "hogehoge") ?? UIColor.black
// 画像の枠の色を決めるとき
imageView.layer.borderColor = UIColor(named: "hugahuga").cgColor ?? UIColor.black.cgColor
意外と簡単にカラーセット呼び出せるんですね。
早くobjc撲滅してSwiftで綺麗にしたい。
ライトモードとダークモードの切り替え時の対応
traitCollectionDidChange
を利用して、モードが切り替わったことを検知して、そのときにカスタムカラーの更新をかけます。
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
[super traitCollectionDidChange:previousTraitCollection];
if (@available(iOS 12.0, *)) {
UIUserInterfaceStyle currentStyle = self.traitCollection.userInterfaceStyle;
UIUserInterfaceStyle previousStyle = previousTraitCollection.userInterfaceStyle;
if (currentStyle != previousStyle) {
//カスタムカラーの更新処理を記述する
}
}
}
Swiftでも基本的に同様の書き方です。
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if #available(iOS 12.0, *) {
let previousStyle = previousTraitCollection?.userInterfaceStyle
let currentStyle = traitCollection.userInterfaceStyle
if previousStyle != currentStyle {
// カスタムカラーの更新処理を記述する
}
}
}