【SwiftUI】独自のStyleを定義してスタイリッシュなコードを書こう
この記事は KINTOテクノロジーズアドベントカレンダー2024 の11日目の記事です🎅🎄
メリークリスマス✌️🎅
KINTOテクノロジーズで my route(iOS) を開発しているRyommです。
本記事ではカスタムスタイルの紹介をします。
はじめに
私がこの書き方を知ったのはApp Dev Tutorialsがきっかけです。
なんてスタイリッシュなんだ…!
カスタムスタイルを使うことで、SwiftUIのコードが格段に読みやすく、洗練されたコードになる…!私もスタイリッシュなコードを書きたい!
そんな衝動に駆られて使い始めましたが、実際かなり便利で読みやすいのでおすすめです。
特に、用途別に乱立した構造体名を覚えていなくても ~~Style() にドットで候補を探せるところが気に入っています。

カスタムスタイルのつくりかた
例えばLabelのカスタムスタイルを作成する場合、 LabelStyle を継承した構造体を作成し、プロトコルに準拠したメソッド(ここでは makeBody(configuration:) )内にスタイルを定義します。
configurationに含まれる値はものによって異なるので都度調べる必要がありますが、LabelStyleConfigurationに関してはTextとImageのViewが入っています。
/// 文字+アイコン のラベルスタイル
struct TrailingIconLabelStyle: LabelStyle {
func makeBody(configuration: Configuration) -> some View {
HStack {
configuration.title
configuration.icon
}
}
}
さらに LabelStyle を拡張して、作成したカスタムスタイルを静的プロパティとして追加すると、呼び出し時に .labelStyle(.trailingIcon) のように呼び出すことができて可読性が向上します。ン〜スタイリッシュ!
extension LabelStyle where Self == TrailingIconLabelStyle {
static var trailingIcon: Self { Self() }
}
もし「spaceを指定したい」など、引数を持たせたい場合はカスタムスタイルにメンバプロパティを追加することで実現できます。
/// 文字+アイコン のラベルスタイル
struct TrailingIconLabelStyle: LabelStyle {
// デフォルト値を設定しておくとドット始まりの呼び出し方法もキープできる
var spacing: CGFloat = 4
func makeBody(configuration: Configuration) -> some View {
HStack(spacing: spacing) {
configuration.title
configuration.icon
}
}
}
// 呼び出し
Label().labelStyle(.trailingIcon) // spaceにはデフォルト値が使われる
Label().labelStyle(TrailingIconLabelStyle(spacing: 2)) // spaceを2に指定
使いどころ
アプリ全体で広く使う共通デザインや、上記の TrailingIconLabelStyle のように普遍的なカスタムスタイルに使うと良いでしょう。
たとえば、my routeではProgressViewで使っています。
ProgressView自体のスタイル設定もですが、ProgressViewを表示中に背景をグレーっぽくするのもスタイルに含めることができます。
struct CommonProgressViewStyle: ProgressViewStyle {
func makeBody(configuration: Configuration) -> some View {
ZStack {
ProgressView(configuration)
.tint(Color(.gray))
.controlSize(.large)
Color(.loadingBackground)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
}
extension ProgressViewStyle where Self == CommonProgressViewStyle {
static var common: Self { Self() }
}
ちなみに、ProgressViewに background() を指定するとProgressViewに必要なサイズのみしか描画されないので、ZStackでColorをProgressViewの下に敷き、背景色が与えられたサイズ全体に広がるようにしています。
このようにスタイルを作成することで、以下のように簡潔でスタイリッシュに書けるようになりました。
struct SomeView: View {
@State var loadingStatus: LoadingStatus
var body: some View {
SomeContentView
.overlay {
if loadingStatus == .loading {
ProgressView()
.progressViewStyle(.common)
}
}
.disabled(loadingStatus == .loading)
}
}
おわりに
カスタムスタイルの紹介でした!
以下のページにあるものはカスタムスタイルを作成できます。
よりスタイリッシュなコードを目指して一歩前進 🦌 🎄
関連記事 | Related Posts
We are hiring!
生成AIエンジニア/AIファーストG/東京・名古屋・大阪・福岡
AIファーストGについて生成AIの活用を通じて、KINTO及びKINTOテクノロジーズへ事業貢献することをミッションに2024年1月に新設されたプロジェクトチームです。生成AI技術は生まれて日が浅く、その技術を業務活用する仕事には定説がありません。
【オープンポジション】「気になる!」方はまずはこちらからご応募ください。/東京・名古屋・大阪・福岡
業務内容国内外のKINTOサービスや、トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、ご経験・ご志向性に応じて配属を決定し、ご活躍いただきます。




