はじめに
【SwiftUI】ListからNavigationLinkで画面遷移する - Swift・iOSの続きです。今回はListからモーダルビューへ画面遷移する実装を試したので記事に残します。
開発環境
- macOS Big Sur 11.2.3
- Xcode 12.4
- Swift 5.3.2
サンプルイメージ
実装
SettingView.swift
import SwiftUI struct SettingView: View { @ObservedObject private var viewModel: SettingViewModel init(viewModel: SettingViewModel) { self.viewModel = viewModel } var body: some View { VStack(alignment: .leading) { Text("設定") .font(.title) .bold() .padding([.leading, .trailing, .top], 25) List { ForEach(viewModel.settings) { setting in Section(header: Text(setting.header)) { ForEach(setting.settingTitles) { titles in Text(titles.title) .onTapGesture { viewModel.selectedSettingTitle = SettingViewModel.SettingTitleType(rawValue: titles.title) ?? .other viewModel.isModalActive.toggle() } .sheet(isPresented: $viewModel.isModalActive) { switch viewModel.selectedSettingTitle { case .edit: Text("編集") case .privacy: Text("プライバシーポリシー") case .license: Text("ライセンス") case .version: Text("バージョン") default: Text("その他") } } } } } } .listStyle(InsetGroupedListStyle()) } } }
SettingViewModel.swift
import Foundation class SettingViewModel: ObservableObject { @Published var isModalActive = false var selectedSettingTitle: SettingTitleType = .other struct SettingTitle: Hashable, Identifiable { var id = UUID() var title : String } struct Setting: Identifiable { var id = UUID() var header: String var settingTitles: [SettingTitle] } var settings: [Setting] = [ Setting(header: "ブックマーク", settingTitles: [SettingTitle(title: "編集")]), Setting(header: "その他", settingTitles: [SettingTitle(title: "プライバシーポリシー"), SettingTitle(title: "ライセンス"), SettingTitle(title: "バージョン")]) ] enum SettingTitleType: String { case edit = "編集" case privacy = "プライバシーポリシー" case license = "ライセンス" case version = "バージョン" case other } }
SceneDelegate.swift
実際にサンプルコードを動かしてみたい場合は、SceneDelegate.swiftの"scene(_:willConnectTo:options:)"を以下のように変更してください。
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { let viewModel = SettingViewModel() let settingView = SettingView(viewModel: viewModel) if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) window.rootViewController = UIHostingController(rootView: settingView) self.window = window window.makeKeyAndVisible() } }
おわりに
実装としても挙動しても改善の余地がありそうと思いつつ、やったことを一旦記事に残しました。
挙動としては、現状Listに表示された各項目(文字列)を選択しないとモーダルが表示されないため、Listの行を選択しても画面遷移できるNavigationLinkと比較すると、ユーザー側としては使いにくそうです。
Listからの画面遷移は基本NavigationLinkを使用したほうが実装がシンプルかつ使い勝手もよくなると感じました。