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
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
OSもどきOS
arkw
0
570
dRuby over BLE
makicamel
2
380
AIとASP.NET Coreで雑Webアプリを作った話
mayuki
0
660
JJUG CCC 2026 Spring: JSpecify で実現する Kotlin フレンドリーな Java API 設計
ternbusty
1
180
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
280
ユニットテストの先へ:テスト技法で要求・仕様を整理するJava開発実践 / Beyond_Unit_Testing_Practical_Java_Development_Techniques_for_Organizing_Requirements_and_Specifications
shimashima35
0
410
Java × distroless で 軽量なコンテナイメージを / Java on Distroless
contour_gara
0
550
New "Type" system on PicoRuby
pocke
1
970
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
270
Snowflake Summitでの新機能 CoCo / CoWork / snowflake-summit-2026-overall-what-new-coco
tatsuhiro
1
150
技術記事、 専門家としてのプログラマ、 言語化
mizchi
13
6.2k
Vite+ Unified Toolchain for the Web
naokihaba
0
320
Featured
See All Featured
Designing for Performance
lara
611
70k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
52k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
950
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
140
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.3k
How to Ace a Technical Interview
jacobian
281
24k
Faster Mobile Websites
deanohume
310
31k
Unsuck your backbone
ammeep
672
58k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
250
The Curse of the Amulet
leimatthew05
1
13k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4k
Are puppies a ranking factor?
jonoalderson
1
3.6k
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"
͋Γ͕ͱ͏͍͟͝·ͨ͠