Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
SwiftUI で複数のアラート表示を管理する
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Yutaka
February 19, 2025
140
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
SwiftUI で複数のアラート表示を管理する
Yutaka
February 19, 2025
More Decks by Yutaka
See All by Yutaka
Swift 6 の地味な (?) アップデート
tajitaji
1
440
2018.01.19 すくすく子育てエンジニア Meetup #1
tajitaji
1
2.2k
mlmodel のコンパイル
tajitaji
0
1.9k
統計・マーケ・R/Python・機械学習 Meetup! #2 2017.10.11
tajitaji
0
200
Vapor プロジェクトの開発に使えそうなツールの紹介
tajitaji
0
520
Server Side Swift, Vapor を触ってみた
tajitaji
0
2.1k
SwiftでのError Handlingを学び直す!
tajitaji
3
830
Featured
See All Featured
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
450
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
350
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
Color Theory Basics | Prateek | Gurzu
gurzu
0
460
Evolving SEO for Evolving Search Engines
ryanjones
0
290
Amusing Abliteration
ianozsvald
1
300
[SF Ruby Conf 2025] Rails X
palkan
2
1.4k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
エンジニアに許された特別な時間の終わり
watany
108
250k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
560
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
600
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
350
Transcript
:VUBLB5BKJLB 4XJGU6*Ͱ ෳͷΞϥʔτදࣔΛཧ͢Δ 
ࣗݾհ w ଟࣛ๛ 5BKJLB:VUBLB w J04ΞϓϦΤϯδχΞ w גࣜձࣾ'0-*0 w
!:VU@5BK w !UBKJUBKJ
4XJGU6*ͰͷΞϥʔτදࣔ ͭͷ߹ struct ContentView: View { @State var isPresented
= false var body: some View { Button("Alert") { isPresented = true } .alert("Alert", isPresented: $isPresented) { Button("Close", role: .cancel) {} } } }
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Λ ද੍ࣔޚϑϥάͱͯ͠อ࣋
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Λ͢
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) {} } } }
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) {} } } } ͦΕͧΕͷΞϥʔτʹରԠ͢Δ ද੍ࣔޚϑϥάΛ࣋ͭ
🎉
ຊʹͪΌΜͱ Ξϥʔτͷදࣔඇදࣔঢ়ଶΛ දݱͰ͖ͯΔɻɻʁ
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͕දࣔ ʢʁʁʁʣ
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͕දࣔ ʢʁʁʁʣ ࣮ࡍʹೋͭͷΞϥʔτ͕ಉ࣌ʹ දࣔ͞ΕΔ͜ͱͳ͍ɻ ͕ɺೋͭͷΞϥʔτ͕දࣔ͞Εͯ ͍ΔΑ͏ͳදݱʹݟ͑Δɻ
վળͯ͠ΈΔ
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Λར༻ͯ͠ ΞϥʔτͷछྨΛఆٛ
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 }
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͕දࣔ
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Λ ࣗલͰ࡞Δ
Ћ
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) }
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 จ຺ΘΓ͘͢ͳͬͨ
ڞ௨Խͯ͠ΈΔ
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) }
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 }} ) } } ͪΐͬͱίʔυΛՃ
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ม
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Λ࡞Βͳͯ͘ྑ͍
ৄ͘͠ϒϩά w IUUQTUBKJUBKJIBUFOBCMPHDPNFOUSZ
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠🙇