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

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

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Yutaka Yutaka
February 19, 2025
120

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Λ࡞Βͳͯ͘ྑ͍