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를 도입하여 광고 서비스 생산성 향상시키기
kakao
PRO
0
170
『ドメイン駆動設計をはじめよう』のモデリングアプローチ
masuda220
PRO
8
540
シェーダーで魅せるMapLibreの動的ラスタータイル
satoshi7190
1
480
Contemporary Test Cases
maaretp
0
130
as(型アサーション)を書く前にできること
marokanatani
10
2.6k
Duckdb-Wasmでローカルダッシュボードを作ってみた
nkforwork
0
120
Quine, Polyglot, 良いコード
qnighy
4
640
距離関数を極める! / SESSIONS 2024
gam0022
0
280
役立つログに取り組もう
irof
28
9.6k
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
110
3rd party scriptでもReactを使いたい! Preact + Reactのハイブリッド開発
righttouch
PRO
1
600
詳細解説! ArrayListの仕組みと実装
yujisoftware
0
580
Featured
See All Featured
It's Worth the Effort
3n
183
27k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
GraphQLとの向き合い方2022年版
quramy
43
13k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Mobile First: as difficult as doing things right
swwweet
222
8.9k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
720
A Modern Web Designer's Workflow
chriscoyier
693
190k
The Art of Programming - Codeland 2020
erikaheidi
52
13k
Producing Creativity
orderedlist
PRO
341
39k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
506
140k
How to train your dragon (web standard)
notwaldorf
88
5.7k
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ͷதͷมԽͰมߋݕͰ͖Δ