Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SwiftUI で複数のアラート表示を管理する

Avatar for Yutaka Yutaka
February 19, 2025
98

SwiftUI で複数のアラート表示を管理する

Avatar for Yutaka

Yutaka

February 19, 2025
Tweet

Transcript

  1. 4XJGU6*ͰͷΞϥʔτදࣔ ͭͷ৔߹  struct ContentView: View { @State var isPresented

    = false var body: some View { Button("Alert") { isPresented = true } .alert("Alert", isPresented: $isPresented) { Button("Close", role: .cancel) {} } } }
  2. 4XJGU6*ͰͷΞϥʔτදࣔ ͭͷ৔߹  struct ContentView: View { @State var isPresented

    = false var body: some View { Button("Alert") { isPresented = true } .alert("Alert", isPresented: $isPresented) { Button("Close", role: .cancel) {} } } } !4UBUFͳ#PPMΛ ද੍ࣔޚϑϥάͱͯ͠อ࣋
  3. 4XJGU6*ͰͷΞϥʔτදࣔ ͭͷ৔߹  struct ContentView: View { @State var isPresented

    = false var body: some View { Button("Alert") { isPresented = true } .alert("Alert", isPresented: $isPresented) { Button("Close", role: .cancel) {} } } } #JOEJOH#PPMܕͰ͋Δ JT1SFTFOUFEΛ౉͢
  4. 4XJGU6*ͰͷΞϥʔτදࣔ ͭͷ৔߹  struct ContentView: View { @State var isPresented1

    = false @State var isPresented2 = false var body: some View { VStack { Button("Alert 1") { isPresented1 = true } Button("Alert 2") { isPresented2 = true } } .alert("Alert 1", isPresented: $isPresented1) { Button("Close", role: .cancel) {} } .alert("Alert 2", isPresented: $isPresented2) { Button("Close", role: .cancel) {} } } }
  5. 4XJGU6*ͰͷΞϥʔτදࣔ ͭͷ৔߹  struct ContentView: View { @State var isPresented1

    = false @State var isPresented2 = false var body: some View { VStack { Button("Alert 1") { isPresented1 = true } Button("Alert 2") { isPresented2 = true } } .alert("Alert 1", isPresented: $isPresented1) { Button("Close", role: .cancel) {} } .alert("Alert 2", isPresented: $isPresented2) { Button("Close", role: .cancel) {} } } } ͦΕͧΕͷΞϥʔτʹରԠ͢Δ ද੍ࣔޚϑϥάΛ࣋ͭ
  6. 4XJGU6*ͰͷΞϥʔτදࣔ ͭͷ৔߹  struct ContentView: View { @State var isPresented1

    = false @State var isPresented2 = false var body: some View { VStack { Button("Alert 1") { isPresented1 = true } Button("Alert 2") { isPresented2 = true } } .alert("Alert 1", isPresented: $isPresented1) { Button("Close", role: .cancel) {} } .alert("Alert 2", isPresented: $isPresented2) { Button("Close", role: .cancel) {} } } } isPresented1 isPresented2 false false ͲͪΒ΋ඇදࣔ true false "MFSU͕දࣔ false true "MFSU͕දࣔ true true "MFSUͱ"MFSU͕දࣔ ʢʁʁʁʣ
  7. 4XJGU6*ͰͷΞϥʔτදࣔ ͭͷ৔߹  struct ContentView: View { @State var isPresented1

    = false @State var isPresented2 = false var body: some View { VStack { Button("Alert 1") { isPresented1 = true } Button("Alert 2") { isPresented2 = true } } .alert("Alert 1", isPresented: $isPresented1) { Button("Close", role: .cancel) {} } .alert("Alert 2", isPresented: $isPresented2) { Button("Close", role: .cancel) {} } } } isPresented1 isPresented2 false false ͲͪΒ΋ඇදࣔ true false "MFSU͕දࣔ false true "MFSU͕දࣔ true true "MFSUͱ"MFSU͕දࣔ ʢʁʁʁʣ ࣮ࡍʹೋͭͷΞϥʔτ͕ಉ࣌ʹ දࣔ͞ΕΔ͜ͱ͸ͳ͍ɻ ͕ɺೋͭͷΞϥʔτ͕දࣔ͞Εͯ ͍ΔΑ͏ͳදݱʹݟ͑Δɻ
  8. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔ  struct ContentView: View { @State var alert: MyAlert?

    var body: some View { VStack { Button("Alert 1") { alert = .alert1 } Button("Alert 2") { alert = .alert2 } } .alert("Alert 1", isPresented: Binding( get: { alert == .alert1 }, set: { if !$0 { alert = nil } } )) { Button("Close", role: .cancel) { alert = nil } } .alert("Alert 2", isPresented: Binding( get: { alert == .alert2 }, set: { if !$0 { alert = nil } } )) { Button("Close", role: .cancel) { alert = nil } } } } enum MyAlert: Equatable { case alert1, alert2 } &OVNΛར༻ͯ͠ ΞϥʔτͷछྨΛఆٛ
  9. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔ  struct ContentView: View { @State var alert: MyAlert?

    var body: some View { VStack { Button("Alert 1") { alert = .alert1 } Button("Alert 2") { alert = .alert2 } } .alert("Alert 1", isPresented: Binding( get: { alert == .alert1 }, set: { if !$0 { alert = nil } } )) { Button("Close", role: .cancel) { alert = nil } } .alert("Alert 2", isPresented: Binding( get: { alert == .alert2 }, set: { if !$0 { alert = nil } } )) { Button("Close", role: .cancel) { alert = nil } } } } enum MyAlert: Equatable { case alert1, alert2 }
  10. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔ  struct ContentView: View { @State var alert: MyAlert?

    var body: some View { VStack { Button("Alert 1") { alert = .alert1 } Button("Alert 2") { alert = .alert2 } } .alert("Alert 1", isPresented: Binding( get: { alert == .alert1 }, set: { if !$0 { alert = nil } } )) { Button("Close", role: .cancel) { alert = nil } } .alert("Alert 2", isPresented: Binding( get: { alert == .alert2 }, set: { if !$0 { alert = nil } } )) { Button("Close", role: .cancel) { alert = nil } } } } enum MyAlert: Equatable { case alert1, alert2 } Ξϥʔτͷදࣔঢ়ଶΛ 0QUJPOBMΛ࢖ͬͯදݱ alert .none ͲͪΒ΋ඇදࣔ .some(.alert1) "MFSU͕දࣔ .some(.alert2) "MFSU͕දࣔ
  11. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔ  struct ContentView: View { @State var alert: MyAlert?

    var body: some View { VStack { Button("Alert 1") { alert = .alert1 } Button("Alert 2") { alert = .alert2 } } .alert("Alert 1", isPresented: Binding( get: { alert == .alert1 }, set: { if !$0 { alert = nil } } )) { Button("Close", role: .cancel) { alert = nil } } .alert("Alert 2", isPresented: Binding( get: { alert == .alert2 }, set: { if !$0 { alert = nil } } )) { Button("Close", role: .cancel) { alert = nil } } } } enum MyAlert: Equatable { case alert1, alert2 } #JOEJOH#PPMΛ ࣗલͰ࡞Δ
  12. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔ  struct ContentView: View { @State var alertState: AlertState<MyAlert>

    = .dismissed var body: some View { VStack { Button("Alert 1") { alertState = .presenting(.alert1) } Button("Alert 2") { alertState = .presenting(.alert2) } } .alert("Alert 1", isPresented: Binding( get: { alertState == .presenting(.alert1) }, set: { if !$0 { alertState = .dismissed } } )) { Button("Close", role: .cancel) { alertState = .dismissed } } .alert("Alert 2", isPresented: Binding( get: { alertState == .presenting(.alert2) }, set: { if !$0 { alertState = .dismissed } } )) { Button("Close", role: .cancel) { alertState = .dismissed } } } } enum MyAlert: Equatable { case alert1, alert2 } 0QUJPOBMͷ୅ΘΓʹ Ξϥʔτͷදࣔঢ়ଶΛ ද͢ઐ༻ͷܕΛ༻ҙ enum AlertState<Alert> where Alert: Equatable { case dismissed case presenting(Alert) }
  13. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔ  struct ContentView: View { @State var alertState: AlertState<MyAlert>

    = .dismissed var body: some View { VStack { Button("Alert 1") { alertState = .presenting(.alert1) } Button("Alert 2") { alertState = .presenting(.alert2) } } .alert("Alert 1", isPresented: Binding( get: { alertState == .presenting(.alert1) }, set: { if !$0 { alertState = .dismissed } } )) { Button("Close", role: .cancel) { alertState = .dismissed } } .alert("Alert 2", isPresented: Binding( get: { alertState == .presenting(.alert2) }, set: { if !$0 { alertState = .dismissed } } )) { Button("Close", role: .cancel) { alertState = .dismissed } } } } enum MyAlert: Equatable { case alert1, alert2 } 0QUJPOBMͷ୅ΘΓʹ Ξϥʔτͷදࣔঢ়ଶΛ ද͢ઐ༻ͷܕΛ༻ҙ enum AlertState<Alert> where Alert: Equatable { case dismissed case presenting(Alert) } w 0QUJPOBMͷ౶ҥߏจ͕࢖͑ͳ ͍ͷͰهड़ྔ͸૿͑Δ w จ຺͸఻ΘΓ΍͘͢ͳͬͨ
  14. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔͷڞ௨Խ  struct ContentView: View { @State var alertState: AlertState<MyAlert>

    = .dismissed var body: some View { VStack { Button("Alert 1") { alertState = .presenting(.alert1) } Button("Alert 2") { alertState = .presenting(.alert2) } } .alert("Alert 1", isPresented: Binding( get: { alertState == .presenting(.alert1) }, set: { if !$0 { alertState = .dismissed } } )) { Button("Close", role: .cancel) { alertState = .dismissed } } .alert("Alert 2", isPresented: Binding( get: { alertState == .presenting(.alert2) }, set: { if !$0 { alertState = .dismissed } } )) { Button("Close", role: .cancel) { alertState = .dismissed } } } } enum MyAlert: Equatable { case alert1, alert2 } ͜͜ͷ#JOEJOHΛຖճ ॻ͔ͳ͍ͱ͍͚ͳ͍ͷ ͸ͪΐͬͱ໘౗ enum AlertState<Alert> where Alert: Equatable { case dismissed case presenting(Alert) }
  15. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔͷڞ௨Խ  protocol AlertCase: Equatable {} protocol AlertStateRepresentable: Equatable {

    associatedtype Alert: AlertCase static var dismissed: Self { get } static func presenting(_ alert: Alert) -> Self } enum AlertState<Alert: AlertCase>: AlertStateRepresentable { case dismissed case presenting(Alert) } extension Binding where Value: AlertStateRepresentable { func isPresented(_ target: Value.Alert) -> Binding<Bool> { .init( get: { wrappedValue == .presenting(target) }, set: { if !$0 { wrappedValue = .dismissed }} ) } } ͪΐͬͱίʔυΛ௥Ճ
  16. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔͷڞ௨Խ  protocol AlertCase: Equatable {} protocol AlertStateRepresentable: Equatable {

    associatedtype Alert: AlertCase static var dismissed: Self { get } static func presenting(_ alert: Alert) -> Self } enum AlertState<Alert: AlertCase>: AlertStateRepresentable { case dismissed case presenting(Alert) } extension Binding where Value: AlertStateRepresentable { func isPresented(_ target: Value.Alert) -> Binding<Bool> { .init( get: { wrappedValue == .presenting(target) }, set: { if !$0 { wrappedValue = .dismissed }} ) } } #JOEJOHʹ JT1SFTFOUFEΛੜ΍ͯ͠ #JOEJOH#PPM΁ม׵
  17. 4XJGU6*Ͱͷෳ਺Ξϥʔτදࣔͷڞ௨Խ  struct ContentView: View { @State var alertState: AlertState<MyAlert>

    = .dismissed var body: some View { VStack { Button("Alert 1") { alertState = .presenting(.alert1) } Button("Alert 2") { alertState = .presenting(.alert2) } } .alert("Alert 1", isPresented: $alertState.isPresented(.alert1)) { Button("Close", role: .cancel) { alertState = .dismissed } } .alert("Alert 2", isPresented: $alertState.isPresented(.alert2)) { Button("Close", role: .cancel) { alertState = .dismissed } } } } enum MyAlert: AlertCase { case alert1, alert2 } ֤ը໘Ͱ#JOEJOH#PPMΛ࡞Βͳͯ͘ྑ͍