この記事はMERPAY TECH OPENNESS MONTHの17日目の記事です。
メルペイiOSエンジニアの@masamichiです。 メルペイで導入している、 iOSアプリで共通UIクラスを使うための仕組みについて紹介します。
背景
メルペイでは、メルペイの機能をSDKとして開発してメルカリアプリに組み込んでいます。SDKにはメルペイで横断的に使用する基本的なUIクラスがあります。例えばメルペイでは統一してテキストラベルの色に #000000
ではなく #333333
を使っていますが、その色を使ったUILabel
のカスタムクラスをPrimaryLabel
として定義しています。他にもUIButton
では、MercariPrimaryFilledButton
やMercariSecondaryOutlinedButton
といったクラスを定義しています。
Label
やButton
といったベースとなるクラスを定義し、継承したクラスでプロパティをカスタムできるようにしています。
import UIKit @IBDesignable public class Label: UILabel { public override init(frame: CGRect) { super.init(frame: frame) setup() } public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } public override func awakeFromNib() { super.awakeFromNib() setup() } public override func prepareForInterfaceBuilder() { super.prepareForInterfaceBuilder() setup() } func setup() { font = font.mp.toPrimaryFont() } } public final class PrimaryLabel: Label { override func setup() { textColor = UIColor.mp.sumi } }
storyboardやxib、コードでViewを開発する時にはデザインを統一するためにこれらのクラスを使用する必要がありますが
- そもそもそんなクラスがあることを知らない
- すでにUIがあることを知らずに自作してしまう場合がある
- storyboard, xibでカスタムクラスを適用するのを忘れてしまう
といった課題がありました。これらの課題を解決するために2つの仕組みを作りました。
仕組み1 UIカタログの作成
どういうUIクラスがあるのかを簡単に確認できるようにするために、SDKのサンプルアプリにUIカタログのページを作りました。
プロジェクト内にクラスが定義されているだけだと、実際にどのような見た目のクラスなのかがわかりにくいということと、コード量が多くなるとそもそもそのクラスの存在に気づくのが難しくなります。
SDKには各フレームワークをメルカリにインテグレーションする前に確認するためのサンプルアプリを作っていますが、そこに共通のUIクラス一覧を表示しました。
このUIカタログを見れば、各UIクラスをすぐに確認できるので、
- そもそもそんなクラスがあることを知らない
- すでにUIがあることを知らずに自作してしまう
といった課題を解決しやすくなりました。
UIカタログによって各クラスの確認はしやすくなりましたが、それだけだとxibでカスタムクラスをセットし忘れるという課題は解決しません。そこでさらにLinterツールを導入して、自動で検出する方法を考えました。
解決策2 Linterツールの導入
storyboard, xibのUIにカスタムクラスが使用されるかを自動で検出するLinterツールを導入しました。
開発者が忘れずにカスタムクラスを使ったり、コードレビューでカスタムクラスが適用されているかを確認するという運用ではセットし忘れを完全に防ぐということはできません。抱えていた課題を解決するには、自動でクラスの設定し忘れを検出する仕組みが必要でした。そこでIBLinterというstoryboard, xibを検査するLinterツールを導入しました。
IBLinterはプロジェクト内のstoryboard, xibファイルを解析し、指定したルールにしたがってエラーや警告を表示してくれます。プロジェクトの Run Script Phase
で実行することで、ビルド時に自動でチェックすることができます。
導入検討時にはIBLinterには特定のカスタムクラスが適用されているかを検査するルールがなかったので、UseBaseClassRule
という新しいルールを作りました。
PRはこちらです → https://github.com/IBDecodable/IBLinter/pull/84
Use Base Class Rule by masamichiueta · Pull Request #84 · IBDecodable/IBLinter · GitHub
このルールでは、特定のUIクラスに設定ファイルで指定したカスタムクラスが適用されていないとビルド時にXcodeで警告がでるようになっています。
例えば、UILabel
に PrimaryLabel
もしくはSecondaryLabel
というクラスが適用されるべき場合は、設定ファイルの .iblinter.yml
に以下のように設定します。
.iblinter.ymlの設定
use_base_class_rule: - element_class: UILabel base_classes: - PrimaryLabel - SecondaryLabel
この状態でカスタムクラスが使われていないラベルが存在するとビルド時に警告が表示されます。
サンプルを作ったので参考にしてみてください。
https://github.com/masamichiueta/UseBaseClassRule
どこまでこのルールを適用すべきかは難しいところですが、全体に使うラベルや、サービスで統一されているボタンなどで使うのがおすすめです。メルペイではUILabel
, UIButton
, UITextField
にこのルールを適用しています。
このルールを導入してからは、既存のxibで漏れていたものを全て置換することができました。
終わりに
メルカリ・メルペイではテックカンパニーらしく、このようにアプリ開発で様々な自動化を取り入れて課題を技術や仕組みで解決しています。
メルペイではミッション・バリューに共感しているiOSエンジニアを募集しています。一緒に働ける仲間をお待ちしております。
明日、MERPAY TECH OPENNESS MONTH の 18日目の記事はメルペイ iOSエンジニア の@celia による「Introducing ViewModel Inputs/Outputs: a modern approach to MVVM architecture」です。iOS2連続です、お楽しみに!!!