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
Swift 5.9 からの Observation はiOS17 未満 からも使えて stru...
Search
yimajo
February 14, 2024
Programming
2
670
Swift 5.9 からの Observation はiOS17 未満 からも使えて struct の変更検知もできるんすかね?
- @_spi(SwiftUI)の部分いついてはよくわからんので削除
-
https://x.com/yimajo/status/1774309468819579146?s=20
yimajo
February 14, 2024
Tweet
Share
More Decks by yimajo
See All by yimajo
良いテストコードのために悪いテストコードを理解する - 不安定なテスト編: iOSアプリ開発ユニットテストの場合
yimajo
22
5.7k
TCAの Shared Stateって どういう仕組みになってんの?
yimajo
0
1.4k
不安定なテストは200種類あんねん
yimajo
3
800
TCA v0.19.0からのSwitchStore/CaseLetが良い
yimajo
0
1.8k
TCAでViewStoreにKeyPath DynamicMemberLookupが使われてる件
yimajo
0
1k
TCAでのClient/Managerの 利用パターンでは副作用のActionやErrorを分離できる
yimajo
0
790
【開催説明資料】iOSアプリ開発のための Functional Architecture 情報共有会
yimajo
0
230
SWORD ART COMBINE
yimajo
1
1.1k
iOSアプリ開発のためのThe Composable Architectureがすごく良いので紹介したい
yimajo
5
4.1k
Other Decks in Programming
See All in Programming
AI時代におけるSRE、 あるいはエンジニアの生存戦略
pyama86
6
1.2k
役立つログに取り組もう
irof
28
9.6k
Amazon Qを使ってIaCを触ろう!
maruto
0
410
色々なIaCツールを実際に触って比較してみる
iriikeita
0
330
Contemporary Test Cases
maaretp
0
140
[Do iOS '24] Ship your app on a Friday...and enjoy your weekend!
polpielladev
0
110
ローコードSaaSのUXを向上させるためのTypeScript
taro28
1
620
どうして僕の作ったクラスが手続き型と言われなきゃいけないんですか
akikogoto
1
120
Snowflake x dbtで作るセキュアでアジャイルなデータ基盤
tsoshiro
2
520
ピラミッド、アイスクリームコーン、SMURF: 自動テストの最適バランスを求めて / Pyramid Ice-Cream-Cone and SMURF
twada
PRO
10
1.3k
CSC509 Lecture 12
javiergs
PRO
0
160
NSOutlineView何もわからん:( 前編 / I Don't Understand About NSOutlineView :( Pt. 1
usagimaru
0
340
Featured
See All Featured
VelocityConf: Rendering Performance Case Studies
addyosmani
325
24k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
42
9.2k
Scaling GitHub
holman
458
140k
Adopting Sorbet at Scale
ufuk
73
9.1k
Rails Girls Zürich Keynote
gr2m
94
13k
The Language of Interfaces
destraynor
154
24k
Code Reviewing Like a Champion
maltzj
520
39k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
506
140k
Embracing the Ebb and Flow
colly
84
4.5k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Building Flexible Design Systems
yeseniaperezcruz
327
38k
A Tale of Four Properties
chriscoyier
156
23k
Transcript
ZJNBKP 4XJGU͔Βͷ0CTFSWBUJPO J04ະຬ͔Β͑ͯ TUSVDUͷมߋݕͰ͖ΔΜ͔͢Ͷʁ
ࣗݾհʹ͔͑ͯ w αφ͖ͷϚϯγϣϯ͕͋Μ·Γͳ͍ w αφ͖ͷΪʔΫϚϯγϣϯʢখʣΛݐ͍ͯͨ w ԯ͘Β͍͍ͩ͘͞
ࣗݾհʹ͔͑ͯ w αφ͖ͷϚϯγϣϯ͕͋Μ·Γͳ͍ w αφ͖ͷΪʔΫϚϯγϣϯʢখʣΛݐ͍ͯͨ w ԯ͘Β͍͍ͩ͘͞
ຊ ࠷ۙͷษڧձͱ͔ͷࢿྉͰʜ
ʮ4XJGUҎ্ͷ0CTFSWBUJPOͰ J04Ҏ্͔ͭDMBTT͡Όͳ͍ͱมߋ ΛݕͰ·ͤΜʯ
ؒҧ͍ͬͯͳ͍͕ɺ J04Ҏ߱ͱ͔ ͦΕຊͷ͜ͱͳΜͰ͔͢ʁ
࣮ࡍ 4XJGUҎ্ͳΒ J04Ҏ্Ͱͳͯ͘ʢJ04Ҏ্ͳΒʣ 4XJGU6*Ͱ0CTFSWBUJPO͑Δ͠ TUSVDUͷࢹͰ͖ʜΔ
࣮ࡍ 4XJGUҎ্ͳΒ J04Ҏ্Ͱͳͯ͘ʢJ04Ҏ্ͳΒʣ 4XJGU6*Ͱ0CTFSWBUJPO͑Δ͠ TUSVDUͷࢹͰ͖ʜΔ ϋϐϋϐϋοϐʔ🎵 ϋοϐʙ
·ͣ 0CTFSWBUJPOͷΈͱʁ
func renderCars() { var car1 = .init() var car2 =
.init() withObservationTracking { print(car1.name) print(car2.name) } onChange: { } } XJUI0CTFSWBUJPO5SBDLJOH @PO$IBOHF 044ͳBQQMFTXJGUΛਅࣅͯ͠ɺόοΫϙʔτΛ࡞ΕΔ
func renderCars() { var car1 = .init() var car2 =
.init() withObservationTracking { print(car1.name) print(car2.name) } onChange: { } } 0CTFSWBUJPO3FHJTUSBS 0CTFSWBUJPO3FHJTUSBS access XJUI0CTFSWBUJPO5SBDLJOH @PO$IBOHF 044ͳBQQMFTXJGUΛਅࣅͯ͠ɺόοΫϙʔτΛ࡞ΕΔ
func renderCars() { var car1 = .init() var car2 =
.init() withObservationTracking { print(car1.name) print(car2.name) } onChange: { } } 0CTFSWBUJPO3FHJTUSBS 0CTFSWBUJPO3FHJTUSBS access @"DDFTT-JTU @"DDFTT-JTU addAccess XJUI0CTFSWBUJPO5SBDLJOH @PO$IBOHF 044ͳBQQMFTXJGUΛਅࣅͯ͠ɺόοΫϙʔτΛ࡞ΕΔ
func renderCars() { var car1 = .init() var car2 =
.init() withObservationTracking { print(car1.name) print(car2.name) } onChange: { } } 0CTFSWBUJPO3FHJTUSBS 0CTFSWBUJPO3FHJTUSBS access merge @"DDFTT-JTU @"DDFTT-JTU addAccess XJUI0CTFSWBUJPO5SBDLJOH @PO$IBOHF 044ͳBQQMFTXJGUΛਅࣅͯ͠ɺόοΫϙʔτΛ࡞ΕΔ
func renderCars() { var car1 = .init() var car2 =
.init() withObservationTracking { print(car1.name) print(car2.name) } onChange: { } } 0CTFSWBUJPO3FHJTUSBS 0CTFSWBUJPO3FHJTUSBS access merge @"DDFTT-JTU @"DDFTT-JTU addAccess XJUI0CTFSWBUJPO5SBDLJOH @PO$IBOHF 044ͳBQQMFTXJGUΛਅࣅͯ͠ɺόοΫϙʔτΛ࡞ΕΔ
DMBTTͷมߋΛݕ͢Δࡍʹ "DDFTT-JTUʹใΛͯ͠ݕ͞Εͨ ͷ͕Կ͔͕Θ͔Δ IUUQTRJJUBDPNZJNBKPJUFNTCCDE
ͳͥ"QQMFJ04Ҏ্ ͱ͍ͯ͠Δͷ͔
J04Ҏ্ͷλʔήοτʹݶఆ͞Ε͍ͯΔ͔Β ʢNBD04 J04 XBUDI04 UW04ʣ w XJUI0CTFSWBUJPO5SBDLJOH @PO$IBOHF w
0CTFSWBUJPO3FHJTUSBS
BQQMFTXJGUϦϙδτϦʹίʔυ͋Δ w XJUI0CTFSWBUJPO5SBDLJOH @PO$IBOHF w IUUQTHJUIVCDPNBQQMFTXJGUCMPCTXJGU3&-&"4&TUEMJC QVCMJD0CTFSWBUJPO4PVSDFT0CTFSWBUJPO 0CTFSWBUJPO5SBDLJOHTXJGU-- w
0CTFSWBUJPO3FHJTUSBS w IUUQTHJUIVCDPNBQQMFTXJGUCMPCTXJGU3&-&"4&TUEMJC QVCMJD0CTFSWBUJPO4PVSDFT0CTFSWBUJPO0CTFSWBUJPO3FHJTUSBSTXJGU
ͦͷ··ਅࣅͨ͠Β0CTFSWBUJPO࡞ΕΔΜ͡ΌͶʁ w όοΫϙʔτͳϥΠϒϥϦ w QPJOUGSFFDPTXJGUQFSDFQUJPO w IUUQTHJUIVCDPNQPJOUGSFFDPTXJGUQFSDFQUJPO w ଞʹ w
POFWDBU0CTFSWBUJPO#1 w IUUQTHJUIVCDPNPOFWDBU0CTFSWBUJPO#1
func renderCars() { var car1 = .init() var car2 =
.init() withPerceptionTracking { print(car1.name) print(car2.name) } onChange: { } } @"DDFTT-JTU 0CTFSWBUJPO3FHJTUSBS @"DDFTT-JTU 0CTFSWBUJPO3FHJTUSBS access merge addAccess XJUI1FSDFQUJPO5SBDLJOH @PO$IBOHF PO$IBOHFܧଓతʹಈ࡞͢ΔΘ͚͡Όͳ͍
XJUI1FSDFQUJPO5SBDLJOH @PO$IBOHF IUUQTHJUIVCDPNQPJOUGSFFDPTXJGUQFSDFQUJPOCMPCNBJO4PVSDFT1FSDFQUJPO1FSDFQUJPO5SBDLJOHTXJGU-$-
withPerceptionTracking { } onChange: { } XJUI1FSDFQUJPO5SBDLJOH @PO$IBOHF withObservationTracking {
} onChange: { } 0CTFSWBUJPO ͑Δ ͑ͳ͍ 0CTFSWBUJPO3FHJTUSBS "DDFTT-JTU 0CTFSWBUJPO
͜͜·Ͱͷ·ͱΊ "QQMFެࣜͰͳ͍#BDL1PSU͞ΕͨͷͳΒ J04͔Β͑Δʢ4XJGUҎ߱ඞਢʣ
4XJGU6*ͷ7JFX͕0CTFSWBUJPO ʹैͬͯ࠶ඳը͞ΕΔ݅
#BDL1PSUΛͬͯ4XJGU6*Ͱͦͷ··͑ΔΘ͚͡Όͳ͍ w มߋΛݕ͢Δ͜ͱͱ4XJGU6*7JFX ͕࠶ඳը͞ΕΔ݅ผ w TXJGUQFSDFQUJPOΛ4XJGU6*Ͱ ͏࣌8JUI1FSDFQUJPO5SBDLJOH Λ͏ struct SomeView:
View { var car = … var body: Some View { WithPerceptionTracking { Text(car.name) } } }
4XJGU0CTFSWBUJPO DMBTTʹ͔͑͠ͳ͍
࠷ॳʹ݁ʢ͋͘·Ͱ༧ʣ
TUSVDU͕"DDFTT-JTUΛ༻͍ͯͦͷมߋΛ௨ ͞ΕΕXJUI0CTFSWBUJPO PO$IBOHF ಈ࡞͢ΔͩΖ͏͔Βɺճ͚ͩಈ͖͑͢͞ Ε͍͍ͷͰ͋ΕͦΕ͓ͦΒ͘Մೳɻ
ͦΕͰ͖Δ͕ɺ͓ͦΒ͘ɺ 4XJGU6*7JFXΛ͏࣌TUSVDUͷΑ͏ʹίϐʔ͞ΕΔ ͷมߋ͞ΕͨͷՕॴͷ7JFXͷΈߋ৽ͱ͍͏͜ͱ Λ܁Γฦ͠ߦ͑ͳ͍ʢͣʣ
func render() { withObservationTracking { } onChange: { } }
ཧղͷͨΊɺXJUI0CTFSWBUJPO5SBDLJOHͰ4XJGU6*ߋ৽͢ΔΠϝʔδ struct SomeView: View { let car = … var body: Some View { Text(“\(car.name)”) FooView() { // userΛมߋ } } } ༧جຊͱͯ͠4XJGU6*ͷ֘7JFXҎԼΛߋ৽͍ͨ͠ɻ ͔͠͠TUSVDUͷมߋͰίϐʔ͞ΕҰҙੑ͕ͳ͘ͳΔͱɺ֘7JFXΛݟ͔ͭΒͳ͍ͷͰߋ৽Ͱ͖ͳ͍ɻ "DDFTT-JTUʹ7JFXͷ໊લΛอ͍࣋ͯ͠ΔΘ͚͡Όͳ͍ɻ
جຊ TUSVDUͷϓϩύςΟͷTFU͕ΞΫηαಈ࡞͠TFU͞Εͨ ͷ͕TFU͞ΕΔલͷͷͱผͱͯ͠ίϐʔ͞ΕΔɻ ʢJOPVUͳTUSVDU@NPEJGZΞΫηα͕ಈ࡞͠ίϐʔ ͞Εͳ͍ʣɻ
ͭ·ΓɺTUSVDUʹ!0CTFSWBCMFϚΫϩ Λར༻Ͱ͖ͯ͠·͏ͱɺ4XJGU6*ͰࠔΔ ͷͰͦͦDMBTTͷΈʹ͞Ε͍ͯΔɻ
͡Ό͋TUSVDU0CTFSWBUJPOͰ ͑ͳ͍ͷ͔ʁ
͕!0CTFSWBCMFDMBTTͳΒྑ͍ɻ ͦͷDMBTTͷϓϩύςΟʹTUSVDUͳ ͷ͕͋Δͱ͢ΔɻTUSVDUͰ͋Δϓϩύς ΟͷมߋͦͷͷΦϒδΣΫτͷมߋ ͱͯ͠ݕͰ͖Δɻ @Observable class Car { struct
Engine { var name = “V8” } @ObservationTracked var name = String() @ObservationTracked var engine = Engine() } DBSFOHJOFOBNFΛม͑ͯɺFOHJOFࣗମ͕ίϐʔ͞ΕΔɻ ݕͰ͖͍ͯΔ͕OBNF͚ͩͷมߋʹͱͲ·͍ͬͯͳ͍ɻ
͔͠͠ TUSVDUࣗମͷมߋΛݕ͍ͨ͠
IUUQTHJUIVCDPNQPJOUGSFFDPTXJGUDPNQPTBCMFBSDIJUFDUVSF 5IF$PNQPTBCMF"SDIJUFDUVSF @ObservableState struct State { @ObservationStateTracked var name =
“” } QPJOUGSFF public protocol ObservableState: Perceptible { var _$id: ObservableStateID { get } mutating func _$willModify() } IUUQTXXXQPJOUGSFFDPFQJTPEFTFQPCTFSWBCMF BSDIJUFDUVSFTUSVDUVSBMJEFOUJUZ
·ͱΊ wJ04ະຬͰެࣜͰͳ͍0CTFSWBUJPO͑Δ wDMBTT͕อ࣋͢ΔTUSVDUݕͰ͖Δ wͨͩTUSVDUͷߏͷมԽΛݕͱ͍͏͔TUSVDUࣗମͷೖΕସΘΓΛݕ w5$"ͳΒJ04ະຬ͔ͭTUSVDUͷதͷมԽͰมߋݕͰ͖Δ