[material-components-ios][MDCAlertController] Key-Value Codingでアラートのボタンの色を個別に設定する
最近、material-components-ios を触ってます
最近マテリアルデザインライクなiOSアプリケーションを作る機会があり、material-components-iosを触っています。
Material Componentsの概要や導入方法については下記記事を参照してください。
[iOS] Material Designの適用をサポートしてくれるライブラリ「Material Components」を試してみた
実際に使おうとすると細かい部分を変えたくなってくる
material-components-ios 自体はマテリアルデザインのコンセプトに忠実に作成されていると思いますが、 実際にアプリに活用する際には「ここだけちょっとマテリアルデザインから外したデザインにしたい」という場面が出てきます。
実際に筆者が経験した要件だと、Dialogsコンポーネントを使って表示した「アラートのボタンの色をボタン毎に変えたい」というものでした。そこで、本記事ではアラートのボタンの色をボタン毎に変える方法をご紹介します。
検証環境
本エントリは以下の環境で検証を行っています。
- macOS High Sierra バージョン 10.13.6
- Xcode Version 9.4.1 (9F2000)
- Apple Swift version 4.1.2 (swiftlang-902.0.54 clang-902.0.39.2)
- CocoaPods 1.5.3
- MaterialComponents (60.1.0)
MDCAlertControllerはボタンの色は一括でしか指定できない
DialogsコンポーネントにはMDCAlertController
というクラスがあり、UIAlertControllerと同じような感覚で使うことができます。
以下はOKとキャンセルボタンを持つアラートを表示するサンプルコードです。
ここで注目していただきたいのがbuttonTitleColor
プロパティでボタンの色を設定している部分です。
このようにbuttonTitleColor
ではボタンの色が全て同じ色になります。
let alertController = MDCAlertController(title: "タイトル", message: "メッセージ") alertController.titleColor = .black alertController.messageColor = .darkGray // OKボタン let okAction = MDCAlertAction(title: "OK") { _ in // ボタンタップ時の処理 } alertController.addAction(okAction) // キャンセルボタン let cancelAction = MDCAlertAction(title: "キャンセル") alertController.addAction(cancelAction) // ボタンの色は一括でしか指定できない! alertController.buttonTitleColor = .blue present(alertController, animated: true)
キャンセルボタンの色をOKボタンの色と違う色にしたい
さて、ここで誰かから「キャンセルとOKは意味合いが異なるからボタンの色を変えたい」と言われたとします。
そこでやることはまず、ボタンの色を個別に設定するプロパティなりメソッドが該当のコンポーネントで提供されているかどうかでしょう。
しかしそのような都合の良いI/Fは備わっていません。そのような場合どうしますか?Material Componentsを使うことは諦めてカスタムのViewを作るのも1つの手だと思います。しかし一方で「ボタンの色を変えたいだけなのにカスタムViewを作るのは面倒...」と思う人もいるでしょう。なんとかしてできないか...そこで使うのがKey-Value Codingです。以下のソースコードを見てください。
// キャンセルボタンの色を変える let actionButtons = alertController.view.value(forKey: "actionButtons") as? [UIButton] let cancelButton = actionButtons?.first { $0.title(for: .normal) == "キャンセル" } cancelButton?.setTitleColor(.darkGray, for: .normal)
実行結果は以下です。
MDCAlertController
の実装を見ると、view
プロパティの実体はMDCAlertControllerView
というクラスでした。
そして、PrivateなプロパティですがMDCAlertControllerView
はactionButtons
というプロパティでボタンのArrayを保持していました。
そこで、value(forKey:)
メソッドを使ってプロパティ名を指定してUIButtonのArrayを取得し、そのタイトルからキャンセルボタンを取得して色を設定しています。
おわりに
今回はKey-Value Codingでアラートのボタンの色を個別に設定する方法をご紹介しました。 注意点として、プロパティ名を指定して対象のオブジェクトを取得しているので、ライブラリのアップデートによりある日突然動作しなくなる恐れはあります。 実装的にはよろしいとは言えないものの、困った時の解決策の一つとしてこういう方法もあるということは知っておいて損はないかと思います。
また、Key-Value Codingについてもっと詳しく知りたいという方はKey-Value Coding Programming Guide をご覧ください。