はじめに
画面で2つの種類のモーダルを出すときにどのように実装したらよいかを考えました。(例えば、新規追加画面と編集画面など)
アプリ起動時
addボタンタップ時
editボタンタップ時
実装例
パターン1
モーダルを起動するボタンごとにsheet修飾子でモーダル表示をする。 デザインとアクションの実装が続き、読みにくい
struct ContentView: View { @State var isShowAddSheet = false @State var isShowEditSheet = false var body: some View { VStack { Text("Hello, World!") Button("add") { self.isShowAddSheet = true } .sheet(isPresented: $isShowAddSheet) { Text("add").background(Color.yellow) } Button("edit") { self.isShowEditSheet = true }.sheet(isPresented: $isShowEditSheet) { Text("edit").background(Color.green) } } } }
パターン2
デザインとアクションが分けられてソースを読みやすくなった気がするが、やりたいことを実現できないのでNG。Viewはsheetをひとつしか持てないようで、addはボタンを押してもモーダル表示されませんでした。editボタンは問題なくモーダル表示されました。
import SwiftUI struct ContentView: View { @State var isShowAddSheet = false @State var isShowEditSheet = false var body: some View { VStack { Text("Hello, World!") Button("add") { self.isShowAddSheet = true } Button("edit") { self.isShowEditSheet = true } } .sheet(isPresented: $isShowAddSheet) { Text("add").background(Color.yellow) } .sheet(isPresented: $isShowEditSheet) { Text("edit").background(Color.green) } } }
パターン3
- モーダル表示にはitem引数を持つ方のsheet修飾子を使う
- item引数には出し分けするモーダルを表すenumを作って使う
モーダル表示にはitem引数を持つ方のsheet修飾子を使う
こちらを使う
public func sheet<Item, Content>(item: Binding<Item?>, onDismiss: (() -> Void)? = nil, @ViewBuilder content: @escaping (Item) -> Content) -> some View where Item : Identifiable, Content : View
item引数には出し分けするモーダルを表すenumを作って使う
画面で新規追加画面と編集画面の2つを出すとします。
下記のようなenumを作成します。
enum SheetType: Int, Identifiable { case add case edit var id: Int { return self.rawValue } }
パターン3実装
import SwiftUI struct ContentView: View { @State var sheetType: SheetType? = nil var body: some View { VStack { Text("Hello, World!") Button("add") { self.sheetType = .add } Button("edit") { self.sheetType = .edit } } .background(Color.gray) .sheet(item: self.$sheetType) { (t) -> AnyView in self.showSheet(type: t) } } private func showSheet(type: SheetType) -> AnyView { switch type { case .add: return AnyView(Text("add").background(Color.yellow)) case .edit: return AnyView(Text("edit").background(Color.green)) } } enum SheetType: Int, Identifiable { case add case edit var id: Int { return self.rawValue } } }
実行
アプリ起動時
addボタンタップ時
editボタンタップ時
結論
他にもっといい方法があるかもしれないが、ひとまずenumを作ってやっておくのが良いとして実装した。