🦅

[SwiftUI]アプリのクオリティを向上させるModifier

2024/12/02に公開

SwiftUIには、便利なModifierが多く用意されています。
今回は一手間でアプリのクオリティを向上させられるModifierをまとめます。
他にもオススメのModifierがあればコメントで教えてください。

見た目に関わるもの

layoutPriority

https://developer.apple.com/documentation/swiftui/view/layoutpriority(_:)

レイアウトの優先度を指定しできます。
数字が大きいいほど表示領域が優先されます。
負の値も指定することができ、デフォルト値は0になっています。

  HStack {
      Text("このTextは優先度を高くしたい")
+         .layoutPriority(1)
  
      Text("このTextは優先度を低くしたい")
          .foregroundStyle(.secondary)
  }

privacySensitive

https://developer.apple.com/documentation/swiftui/view/privacysensitive(_:)

Viewに、センシティブな情報が含まれていることを指定できます。
アプリが非アクティブになった際に、指定したViewが自動的にマスクされます。

デザインをカスタマイズしたい場合はこちらを使用します。

アクティブ 非アクティブ
  VStack(alignment: .leading) {
      Text("パスワード")
  
      Text("Password")
+         .privacySensitive()
  }

入力に関わるもの

textContentType

https://developer.apple.com/documentation/swiftui/view/textcontenttype(_:)-ufdv

TextFieldの入力に期待される内容の種類を指定できます。
たとえば、.emailAddressを指定すると、連絡先アプリに登録されている自身のメールアドレスが候補として表示されます。

指定できるタイプはこちらで確認できます。

  TextField("メール", text: $emailAddress)
      .textFieldStyle(.roundedBorder)
+     .textContentType(.emailAddress)

keyboardType

https://developer.apple.com/documentation/swiftui/view/keyboardtype(_:)

テキスト入力に使用されるキーボードの種類を指定できます。
たとえば、

  • @.が入力しやすくなる.emailAddress
  • @#が入力しやすくなる.twitter

などが指定できます。
指定できるタイプはこちらで確認できます。

  TextField("メール", text: $emailAddress)
      .textFieldStyle(.roundedBorder)
+     .keyboardType(.emailAddress)

submitLabel

https://developer.apple.com/documentation/swiftui/view/submitlabel(_:)

キーボードのreturn改行の表示を変更できます。
指定できるラベルはこちらで確認できます。

  TextField("検索", text: $searchText)
      .textFieldStyle(.roundedBorder)
+     .submitLabel(.search)

操作に関わるもの

textSelection

Textを長押しした際に、クリップボードにコピーするためのポップオーバーを表示できます。

  VStack(alignment: .leading) {
      Text("ユーザID")
  
      Text("@RyoDeveloper")
+         .textSelection(.enabled)
  }

focused

https://developer.apple.com/documentation/swiftui/view/focused(_:)

フォーカス状態を制御できます
たとえば、入力画面を表示した際に、自動で特定の入力欄にフォーカスを当てることができます。

  TextField("検索", text: $searchText)
      .textFieldStyle(.roundedBorder)
      .submitLabel(.search)
+     .focused($focus)

複数のTextField間でfocusを移動させる例

Viewの表示時に自動でメール入力欄にフォーカスを当て、returnキーでフォーカスをパスワード入力欄に移動させる例です。

struct ContentView: View {
    enum Field {
        case emailAddress
        case password
    }

    @State private var emailAddress = ""
    @State private var password = ""
    @FocusState private var focus: Field?

    var body: some View {
        Form {
            TextField("メール", text: $emailAddress)
                .focused(self.$focus, equals: Field.emailAddress)
                .onSubmit {
                    focus = .password
                }
                .onAppear {
                    focus = .emailAddress
                }
            TextField("パスワード", text: $password)
                .focused(self.$focus, equals: Field.password)
                .onSubmit {
                    focus = nil
                }
        }
    }
}
初期値 returnタップ

keyboardShortcut

https://developer.apple.com/documentation/swiftui/view/keyboardshortcut(_:)

キーボードショートカットを設定できます。
通常のキーと組み合わせの他にも、デフォルトアクションの設定もできます。
Buttonに.defaultActionを指定すると、returnキーでアクションが実行されるようになり、フォントが太字になります。

ボタンの役割によっては、設定したボタンの見た目に追加の影響が及びます。例えば、プライマリボタンのラベルには太い文字のテキストが、破壊的なボタンには赤色のテキストが使用される場合があります。

https://developer.apple.com/jp/design/human-interface-guidelines/buttons#Role

  VStack {
      Spacer()
  
      Text("ダウンロードが完了しました。")
          .font(.title2)
  
      Spacer()
  
      Button {
      } label: {
          Text("閉じる")
              .frame(maxWidth: .infinity)
      }
      .buttonStyle(.borderedProminent)
      .controlSize(.large)
+     .keyboardShortcut(.defaultAction)
  }

その他

sensoryFeedback

https://developer.apple.com/documentation/swiftui/view/sensoryfeedback(trigger:_:)

触覚フィードバックを提供できます。
値の変更を監視し、変更された値に応じて適切な触覚フィードバックを提供できます。
たとえば、お気に入りボタンをタップしたときや、入力のバリデーションチェックに失敗した時などに有効です。

  Button {
      isLike.toggle()
  } label: {
      Image(systemName: isLike ? "heart.fill" : "heart")
          .contentTransition(.symbolEffect(.replace.offUp))
  }
+ .sensoryFeedback(trigger: isLike) { oldValue, newValue in
+     return .selection
+ }

Discussion