1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【SwiftUI】この世でいちばんわかりやすいビューモディファイアの作り方

Last updated at Posted at 2021-07-04

この投稿は何?

SwiftUIフレームワークを使ったアプリ開発では、いくつものビューを組み合わせて画面を構築していきます。そのビューの外観や振る舞いを設定するために使用するのがビューモディファイアです。
ここでは、独自のビューモディファイアを定義して呼び出す方法について、実践・解説します。

実行環境

macOS 11.4
Xcode 12.5.1
Swift 5.4

ハンズオン

作成するモディファイアは、「ビューにチェックマークをつける」というものです。

スクリーンショット 2021-07-04 23.09.30.png

ViewModifierプロトコル

新しいファイルを作成して、そこにMarkという名前の構造体を定義します。

Mark型
import SwiftUI

struct Mark: ViewModifier {
    func body(content: Content) -> some View {
        // ビューを返す
    }
}

「モディファイアとして呼び出せるメソッド」を実装するには、その型をViewModifierプロトコルに適合させる必要があります。ViewModifierプロトコルは、型にbody(_:)メソッドの実装を要求します。
このメソッドが受け取る’content’パラメータは、モディファイアの適用対象となるビューを示します。そして、返り値の型として宣言されているsome Viewが、モディファイア適用後のビューです。

body(_:)メソッド

ここでは、適用対象となるビューの左側に「緑色のチェックマーク」を配置します。ビュービルダー形式でコードを記述することができます。

Mark型
struct Mark: ViewModifier {
    func body(content: Content) -> some View {
        HStack {
            Image(systemName: "checkmark.circle")
                .foregroundColor(.green)
            content
        }
    }
}

以上で、独自のモディファイアを定義することができました。

モディファイアを呼び出す

作成したモディファイアを適用するには、ビューのmodifier(_:)メソッドを呼び出します。

ContentView
struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .modifier(Mark())
    }
}

プレビューでは、テキストの左側に「緑色のチェックマーク」が配置されます。
ただし、このコードは「一般的なビューモディファイア」とは呼び出し方が異なっていることがわかります。
.marked()のように、「モディファイアらしい方法」で呼び出したいところです。

モディファイアらしい呼び出し方

View型を拡張して、モディファイアの望ましい呼び出し方法を実装します。

Mark.swift
struct Mark: ViewModifier {
    func body(content: Content) -> some View {...}
}

extension View {
    func marked() -> some View {
        return self.modifier(Mark())
    }
}

理想的なメソッド名を宣言して、some View型を返すようにします。メソッドのボディでは、自身のインスタンスに対して「元のモディファイアメソッド」を適用したビューを返すでけです。

これで、モディファイアはよりSwiftUIっぽい形式で呼び出せるようになります。

Content.swift
struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .marked()
    }
}

パラメータを受け取るモディファイア

マークの種類を変更するために、モディファイアがパラメータを受け取ることもできます。

Mark.swift
struct Mark: ViewModifier {
    var isChecked: Bool

    func body(content: Content) -> some View {
        HStack {
            if isChecked {
                Image(systemName: "checkmark.circle")
                    .foregroundColor(.green)
            } else {
                Image(systemName: "xmark.circle")
                    .foregroundColor(.red)
            }
            content
        }
    }
}
extension View {
    func mark(isChecked: Bool) -> some View {
        return self.modifier(Mark(isChecked: isChecked))
    }
}

ここでは、「緑のチェック」か「赤のバツ」のいずれかをマークするようにモディファイアを定義しました。

呼び出し側のコードでは、モディファイアにBool値を指定します。

Content.swift
struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .mark(isChecked: false)
    }
}

スクリーンショット 2021-07-04 23.42.08.png

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?