Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
SwiftUI Viewの責務分離
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
elmetal
PRO
February 18, 2025
Programming
510
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
SwiftUI Viewの責務分離
elmetal
PRO
February 18, 2025
More Decks by elmetal
See All by elmetal
The Integrity of Making: Extending Xcode Previews with MCP
elmetal
PRO
0
36
Generating DocC with AI
elmetal
PRO
0
65
A Swift Way to Blog
elmetal
PRO
0
180
Designing DocC for Clarity and Beauty
elmetal
PRO
0
120
サイボウズiOSアプリのマルチモジュール 2024
elmetal
PRO
0
140
開発を加速する共有Swift Package実践
elmetal
PRO
0
1.4k
Resolve Nested ObservableObject issues in Observation
elmetal
PRO
0
430
ObservationSallowDive
elmetal
PRO
1
380
「サイボウズ Office」 の iOSアプリをリニューアルした話 / Renewal "Cybozu Office" iOS App
elmetal
PRO
0
750
Other Decks in Programming
See All in Programming
Creating Composable Callables in Contemporary C++
rollbear
0
160
AIだと陥りがちなJakarta EE最新技術への移行時の落とし穴と解決策
tnagao7
0
120
「AIで開発し、AIを届ける」をEvalでつなぐ 〜AIネイティブに始めるプロダクト開発の実践〜 / Connecting "Develop with AI, deliver AI" with Eval
rkaga
4
5.4k
はてなアカウント基盤 State of the Union
cockscomb
0
520
AIで効率化できた業務・日常
ochtum
0
140
dRuby over BLE
makicamel
2
390
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
300
OSもどきOS
arkw
0
590
依存関係から依存物へ―Dependencyという言葉の歴史をひも解く
j_lee
0
130
New "Type" system on PicoRuby
pocke
1
1k
肥大化するレガシーコードに立ち向かうためのインターフェース分離と依存の逆転 / JJUG CCC 2026 Spring
hirokunimaeta
0
610
AIを活用したE2Eテスト実装効率化のあゆみ / ebisu-mobile-14-kotetu
kotetuco
0
130
Featured
See All Featured
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
370
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.4k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
610
Practical Orchestrator
shlominoach
191
11k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.6k
Believing is Seeing
oripsolob
1
150
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
44k
Ethics towards AI in product and experience design
skipperchong
2
310
Docker and Python
trallard
47
3.9k
Typedesign – Prime Four
hannesfritz
42
3.1k
Automating Front-end Workflow
addyosmani
1370
210k
Transcript
4XJGU6*7JFXͷ .PCJMF"$504"," FMNFUBM
"CPVUNF !FM@NFUBM@ J04"QQ %FWFMPQFS ڝഅ ରઓήʔϜ ҭࣇ ෳνʔϜͷ ٕज़ࢧԉ
4XJGU6*7JFXେ͖͘ͳΓ͕ͪ
ͨͩͷϦετ struct ContentView: View { @State var pokemons: [Pokemon] =
[Pokemon(name: "Sprigatito"), Pokemon(name: "Fuecoco"), Pokemon(name: "Quaxly")] var body: some View { NavigationView { PokemonList(data: pokemons) .listStyle(.grid) } } }
αʔόʔ͔ΒσʔλΛGFUDI͢Δ struct ContentView: View { @State var pokemons: [Pokemon] =
[] var body: some View { NavigationView { PokemonList(data: pokemons) .listStyle(.grid) .task { do { pokemons = try await PokeRepository.mock.fetch() } catch { // some errors } } } } }
σʔλ͕݅ͷέʔεΛՃ struct ContentView: View { @State var pokemons: [Pokemon] =
[] var body: some View { NavigationView { if pokemons.isEmpty { Text("no pokemons") } else { PokemonList(data: pokemons) .listStyle(.grid) } } .task { do { pokemons = try await PokeRepository.mock.fetch() } catch { // some errors } } } }
௨৴ΤϥʔͷέʔεΛՃ struct ContentView: View { @State var pokemons: [Pokemon] =
[] @State var error: MyError? var body: some View { NavigationView { if let error { switch error { case .network: Text("network error") } } else if pokemons.isEmpty { Text("no pokemons") } else { PokemonList(data: pokemons) .listStyle(.grid) } } .task { do { pokemons = try await PokeRepository.mock.fetch() self.error = nil } catch { self.error = .network } } } }
ओཁ෦͕͍ΒΕ͍ͯ͘ struct ContentView: View { @State var pokemons: [Pokemon] =
[] @State var error: MyError? var body: some View { NavigationView { if let error { switch error { case .network: Text("network error") } } else if pokemons.isEmpty { Text("no pokemons") } else { PokemonList(data: pokemons) .listStyle(.grid) } } .task { do { pokemons = try await PokeRepository.mock.fetch() self.error = nil } catch { self.error = .network } } } } ओཁ෦͜Ε͚ͩ
7JFXͷׂ
ίʔφʔέʔεΛ struct ContentView: View { @State var pokemons: [Pokemon] =
[] @State var error: MyError? var body: some View { NavigationView { PokemonList(data: pokemons) .listStyle(.grid) .task { do { pokemons = try await PokeRepository.mock.fetch() self.error = nil } catch { self.error = .network } } .overlay { if let error { switch error { case .network: Text("network error") } } else if pokemons.isEmpty { Text("no pokemons") } } } } } ΤϥʔΛPWFSMBZϒϩοΫ
$POUFOU6OBWBJMBCMF7JFXΛར༻ struct ContentView: View { @State var pokemons: [Pokemon] =
[] @State var error: MyError? var body: some View { NavigationView { PokemonList(data: pokemons) .listStyle(.grid) .task { do { pokemons = try await PokeRepository.mock.fetch() self.error = nil } catch { self.error = .network } } .overlay { if let error { switch error { case .network: ContentUnavailableView("network error", systemImage: "wifi.slash", description: Text("check your internet connection")) } } else if pokemons.isEmpty { ContentUnavailableView("no pokemons", systemImage: "circle") } } } } } ۭྻ ωοτϫʔΫΤϥʔ
ۭྻͷදࣔఆٛଆͰߦ͏ struct GridPokeListStyle: PokeListStyle { var columns = [GridItem(.adaptive(minimum: 80),
spacing: 16)] func makeBody(configuration: PokeListConfiguration) -> some View { ScrollView { LazyVGrid(columns: columns, spacing: 16) { ForEach(configuration.pokemons, id: \.self) { pokemon in PokemonView(pokemon: pokemon) } } .padding([.horizontal], 16) } .overlay { if configuration.pokemons.isEmpty { ContentUnavailableView("no pokemons", systemImage: "circle") } } } }
ۭྻͷදࣔఆٛଆͰߦ͏ struct ContentView: View { @State var pokemons: [Pokemon] =
[] @State var error: MyError? var body: some View { NavigationView { PokemonList(data: pokemons) .listStyle(.grid) .task { do { pokemons = try await PokeRepository.mock.fetch() self.error = nil } catch { self.error = .network } } .overlay { if let error { switch error { case .network: ContentUnavailableView("network error", systemImage: "wifi.slash", description: Text("check your internet connection")) } } } } } }
એ
4XJGU6*7JFX$PEJOH(VJEFMJOFT https://github.com/cybozu/swiftui-view-coding-guidelines https://cybozu.github.io/swiftui-view-coding-guidelines/documentation/swiftuiviewcodingguidelines/ %PD$ (JU)VC3FQP
2"
͋Γ͕ͱ͏͍͟͝·ͨ͠