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
880
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
6.1k
TCAの Shared Stateって どういう仕組みになってんの?
yimajo
0
1.9k
不安定なテストは200種類あんねん
yimajo
3
910
TCA v0.19.0からのSwitchStore/CaseLetが良い
yimajo
0
1.9k
TCAでViewStoreにKeyPath DynamicMemberLookupが使われてる件
yimajo
0
1.1k
TCAでのClient/Managerの 利用パターンでは副作用のActionやErrorを分離できる
yimajo
0
850
【開催説明資料】iOSアプリ開発のための Functional Architecture 情報共有会
yimajo
0
250
SWORD ART COMBINE
yimajo
1
1.2k
iOSアプリ開発のためのThe Composable Architectureがすごく良いので紹介したい
yimajo
5
4.2k
Other Decks in Programming
See All in Programming
DomainException と Result 型で作る型安全なエラーハンドリング
karszawa
0
460
爆速スッキリ! Rspack 移行の成果と道のり - Muddy Web #11
dora1998
1
150
自分のために作ったアプリが、グローバルに使われるまで / Indie App Development Lunch LT
pixyzehn
1
130
goにおける コネクションプールの仕組み を軽く掘って見た
aronokuyama
0
140
The Evolution of Enterprise Java with Jakarta EE 11 and Beyond
ivargrimstad
0
1k
複雑なフォームと複雑な状態管理にどう向き合うか / #newt_techtalk vol. 15
izumin5210
4
3.4k
OUPC2024 Day 1 解説
kowerkoint
0
400
AIエージェントを活用したアプリ開発手法の模索
kumamotone
1
750
2025/3/18 サービスの成長で生じる幅広いパフォーマンスの問題を、 AIで手軽に解決する
shirahama_x
0
160
RubyKaigiで手に入れた HHKB Studioのための HIDRawドライバ
iberianpig
0
1k
Fluent UI Blazor 5 (alpha)の紹介
tomokusaba
0
150
CTFのWebにおける⾼難易度問題について
hamayanhamayan
1
990
Featured
See All Featured
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.7k
Building Applications with DynamoDB
mza
94
6.3k
Speed Design
sergeychernyshev
28
870
Optimizing for Happiness
mojombo
377
70k
Gamification - CAS2011
davidbonilla
81
5.2k
Making the Leap to Tech Lead
cromwellryan
133
9.2k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
45
9.5k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
The Pragmatic Product Professional
lauravandoore
33
6.5k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.1k
Thoughts on Productivity
jonyablonski
69
4.5k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
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ͷதͷมԽͰมߋݕͰ͖Δ