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と比較してみた時のFlutter
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Tatsuya Tanaka
June 23, 2020
Programming
2k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
SwiftUIと比較してみた時のFlutter
https://yj-meetup.connpass.com/event/178577/
#wwdctokyo
Tatsuya Tanaka
June 23, 2020
More Decks by Tatsuya Tanaka
See All by Tatsuya Tanaka
iPhoneのセンサー情報をmacOSアプリでリアルタイム活用するための技術
tattn
1
770
Better use of SwiftUI
tattn
0
500
Swift Concurrencyによる安全で快適な非同期処理
tattn
2
1.4k
iOSアプリの技術選択2022
tattn
7
4k
Widget Suggestions 対応と ヤフーの新OS対応
tattn
1
1.4k
WidgetKitで良い体験を作るには / Good experience with WidgetKit
tattn
2
1.9k
既存アプリにSwiftUIをどう組み込んでいくか
tattn
8
2.5k
iOS 14からのアプリ内課金
tattn
5
3.1k
iOS 14の位置情報系アップデート
tattn
0
22k
Other Decks in Programming
See All in Programming
The ROI of Quarkus for Spring Boot Applications
hollycummins
0
140
LaravelLive Japan の裏方のすべて — 第188回 PHP勉強会@東京 (2026-06-24)
suguruooki
2
110
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
7.8k
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
230
Performance Engineering for Everyone
elenatanasoiu
0
210
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.7k
RTSPクライアントを自作してみた話
simotin13
0
630
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
270
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
280
気圧・高度・GPSを記録&可視化するアプリ「Koudo」を作った話
hjmkth
1
320
ADKを使って簡単にAIエージェントを作ってみよう
k1mu21
0
280
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.3k
Featured
See All Featured
Designing for Timeless Needs
cassininazir
1
260
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.7k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Marketing to machines
jonoalderson
1
5.5k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.1k
Design in an AI World
tapps
1
250
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
The browser strikes back
jonoalderson
0
1.3k
Site-Speed That Sticks
csswizardry
13
1.2k
エンジニアに許された特別な時間の終わり
watany
107
250k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
Transcript
SwiftUIͱൺֱͯ͠Έͨ࣌ͷFlutter ాதୡ (@tattn) #wwdctokyo
ాத ୡ / ͨͳͨͭ (@tattn) • Yahoo!ΧʔφϏ ←Yahoo!Ҋ • iOSΞϓϦΤϯδχΞ
• ৽ٕज़ͷݕূ @tattn @tanakasan2525 @tattn Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved.
όʔνϟϧLODGEͲ͏Ͱ͠ΐ͏͔ʁ https://note.com/lodge/n/nfa4a40c057b1 3DϞσϥʔͱUnity͍͕͍Εҙ֎ͱ؆୯ʹ࡞Ε·͢ʂ
SwiftUIͬͯΈ·͔ͨ͠ʁ YES NO (clusterͷΤϞʔγϣϯ ͰԠ͍ͩ͘͞)
ࠓͷSwiftUI·ͩͭΒΈ͕ଟ͍ʂ
ݸਓతʹSwiftUIͰ࡞͍ͬͯͨΞϓϦΛ FlutterʹҠߦͨ͠Γɺ ۀͰFlutterΛݕূͨ͠Γ͍ͯ͠·͢
WWDC20લͱͷ͜ͱͰ Flutterͱൺֱͭͭ͠ SwiftUIͷਐԽʹظ͢ΔLTΛ͠·͢
Flutterͱ
Flutterͱ • GoogleʹΑͬͯ։ൃ͞ΕͨΦʔϓϯιʔεϞόΠϧΞϓϦSDK • ΫϩεϓϥοτϑΥʔϜ (iOS, Android, Web, macOS) •
DartͰهड़͢Δ • ίϯϙʔωϯτࢦɺϗοτϦϩʔυͳͲͷ ࠓͲ͖ͷઃܭػೳ
Flutterͷ͘͠Έ
Flutterͷ෦ https://flutter.dev/docs/resources/technical-overview ಠࣗͷϨϯμϦϯάΤϯδϯ(Skia) ͰUIViewʹඳը͠ɺUIΛදࣔ
ΈΜͳେ͖View Hierarchy FlutterViewControllerͷFlutterViewʹશͯඳը͞Ε͍ͯΔ (ScrollViewݟ͑ͳ͍ͱ͜Ζʹஔ) ͪͳΈʹ.xcworkspace࡞ΒΕΔͷͰ ωΠςΟϒͷσόοάXcodeͰͰ͖Δ
ίʔυ࣮ߦͷ͘͠Έ ϦϦʔεϏϧυ Dartίʔυ ػցޠ ίϯύΠϧ σόοάϏϧυ ػցޠ+Dart ࣮ߦதʹඞཁͳ෦͚ͩίϯύΠϧ͞ΕΔ (JIT) →ϗοτϦϩʔυ͕ޮ͘
࣮ߦલʹશͯίϯύΠϧ͞ΕΔ(AOT) →ಈ࡞͕͍
FlutterͰͷUIͷ࡞Γํ (ϘλϯΛԡͨ͠Β1૿͑ΔΞϓϦ)
ϘλϯΛԡ͢ͱ1૿͑Δը໘ (SwiftUI) struct ContentView: View { @State var count =
0 var body: some View { VStack { Text("Count: \(count)") .font(.largeTitle) Spacer() .frame(height: 20) Button(action: { self.count += 1 }, label: { Text("Increment") }) } } }
ϘλϯΛԡ͢ͱ1૿͑Δը໘ (Flutter) class CounterApp extends StatefulWidget { @override _CounterAppState createState()
=> _CounterAppState(); } class _CounterAppState extends State<CounterApp> { int _count = 0; @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text('Count: $_count', style: Theme.of(context).textTheme.headline5), SizedBox(height: 20), FlatButton( child: Text('Increment'), onPressed: () => setState(() => _count++), ) ], ), ); } } ͪΐͬͱίʔυྔଟ͘ݟ͑·͕͢ɺ εχϖοτͰࣗಈੜ͞ΕΔͷͰهड़ྔಉ͘͡Β͍
ϘλϯΛԡ͢ͱ1૿͑Δը໘ (Flutter) class _CounterAppState extends State<CounterApp> { int _count =
0; @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text('Count: $_count', style: Theme.of(context).textTheme.headline5), SizedBox(height: 20), FlatButton( child: Text('Increment'), onPressed: () => setState(() => _count++), ) ], ), ); } } ࣗಈੜ෦ΛΧοτͯ͠ຊ࣭ͷΈʹ͢Δͱ͜Μͳײ͡
ϘλϯΛԡ͢ͱ1૿͑Δը໘ (Flutter | SwiftUI) ࣅͨΑ͏ͳײ֮Ͱॻ͚·͢ class _CounterAppState extends State<CounterApp> {
int _count = 0; @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text('Count: $_count', ɹɹ style: Theme.of(context).textTheme.headline5), SizedBox(height: 20), FlatButton( child: Text('Increment'), onPressed: () => setState(() => _count++), ) ], ), ); } } struct ContentView: View { @State var count = 0 var body: some View { VStack { Text("Count: \(count)") .font(.largeTitle) Spacer() .frame(height: 20) Button(action: { self.count += 1 }, label: { Text("Increment") }) } } }
Flutterͷྑ͍ͱ͜Ζ (vs SwiftUI)
Hot Reload͕ "ͪΌΜͱ" ͑Δ • ⌘+SΛԡ͢ͱอଘ͞ΕࣗಈͰView͕ߋ৽͞ΕΔ • γϛϡϨʔλͰ࣮ػͰ͑Δ • ϓϩδΣΫτ͕େ͖ͯ͘ө·Ͱ1ඵ͘Β͍
• Ϧϩʔυલͷঢ়ଶ͕Δ
Hot Reload͕ "ͪΌΜͱ" ͑Δ • ⌘+SΛԡ͢ͱอଘ͞ΕࣗಈͰView͕ߋ৽͞ΕΔ • γϛϡϨʔλͰ࣮ػͰ͑Δ • ϓϩδΣΫτ͕େ͖ͯ͘ө·Ͱ1ඵ͘Β͍
• Ϧϩʔυલͷঢ়ଶ͕Δ SwiftUIͷϓϨϏϡʔίϯϙʔωϯτ୯Ґ͕جຊͰ͕͢ɺ FlutterσόοάϏϧυதͷΞϓϦΛಈతʹॻ͖͑Δײ֮
SwiftUIΑΓॊೈ • ϨΠΞτͰ࣮ݱͰ͖ͳ͍έʔε΄΅ͳͦ͞͏ • Γͳ͍ػೳΛิ͏খ͞ͳϥΠϒϥϦ͕ଟ͍ • ։ൃαΠΫϧ͕ૣ͘ɺ͙͢ʹΔ
SwiftUIΑΓॊೈ • ϨΠΞτͰ࣮ݱͰ͖ͳ͍έʔε΄΅ͳͦ͞͏ • Γͳ͍ػೳΛิ͏খ͞ͳϥΠϒϥϦ͕ଟ͍ • ։ൃαΠΫϧ͕ૣ͘ɺ͙͢ʹΔ • FlutterͷϑϨʔϜϫʔΫଆDart෦ ΞϓϦͷσόοά࣌ʹϒϨʔΫϙΠϯτΛஔ͍ͯ
σόοάͰ͖ΔʂͷͰमਖ਼ͷෑډ͕͍ (ͤΔਓ͕ଟ͍)
AndroidͰಈ͘ʂʂʂ
ωΠςΟϒͷػೳͲ͏͢Δͷʁ
ωΠςΟϒػೳͷݺͼग़͠ํ PlatformView PlatformChannel UIViewΛͬͯiOSͷΈͰUIΛಈ͔͠ɺ දࣔ݁ՌΛSkiaʹૹͬͯϨϯμϦϯά͢Δɻ →ωΠςΟϒͷViewΛFlutterͷWidgetʹΈࠐΊΔ ωΠςΟϒͰػೳΛ࣮͠ɺDart͔Βݺͼग़͢Έɻ ૬ޓʹσʔλͷΓऔΓ͕Ͱ͖Δ (σʔλܕͷ੍ݶ͋Δ) ͲͪΒSwift
/Kotlin Ͱॻ͚Δʂ
ωΠςΟϒΞϓϦʹFlutterΛຒΊࠐΉํ๏͋Δ Add to App ɾCocoaPodsͰFlutterΞϓϦΛऔΓࠐΉ ɾίϚϯυͰFrameworkԽͯ͠औΓࠐΉ ɾpodspecͰFrameworkԽΛCocoaPodsʹ·͔ͤͯऔΓࠐΉ IUUQTqVUUFSEFWEPDTEFWFMPQNFOUBEEUPBQQ ͳͲͷํ๏ͰطଘͷωΠςΟϒΞϓϦʹ FlutterΛ෦ಋೖ͢Δ͜ͱͰ͖·͢ɻ
(FlutterͷUI1ຕͷViewControllerͱͯ͠औΓѻ͑Δ)
SwiftUIͷํ͕ྑ͍෦
SwiftUIͷྑ͍ͱ͜Ζ ϝιουνΣʔϯ (modifier) ʹΑΔViewͷΧελϚΠζ ೖΕࢠΛݮΒͤͯಡΈ͍͢ɻ (ͨΓલͰ͕͢)ωΠςΟϒͷػೳΛ͔ΜͨΜʹσόοάͰ͖Δɻ Swiftຊʹྑ͍ݴޠɻ Text("WWDC") .padding() .border(Color.red,
width: 3) Container( decoration: BoxDecoration( border: Border.all(color: Colors.red, width: 3), ), padding: const EdgeInsets.all(8), child: Text("WWDC"), ) Container( decoration: BoxDecoration( border: Border.all(color: Colors.red, width: 3), ), child: Padding( padding: const EdgeInsets.all(8), child: Text("WWDC"), ), ), ωετΛݮΒͨ͢ΊʹpaddingΛ ҾͰࢦఆͰ͖ΔWidget͋Δ
͜Ε͔Β࢝·ΔWWDCʹ ظ͢Δ͜ͱ
Apple͞Μ͓ئ͍͠·͢ʂ ɾHot ReloadͷਐԽʹظʂ ɹɹɾσόοάϏϧυͰಈ͔ͯ͠ΔΞϓϦΛ ɹɹɹঢ়ଶΛͭͭ͠ॻ͖͍͑ͨ ɾViewͷΧελϚΠζੑΛߴͯ͘͠΄͍͠ʂ ɹɹɾཪʹ͍ΔUIKitAppKitͷViewʹ৮ΕΔΈͰྑ͍Ͱ͢ ɾWebͰಈ͘Α͏ʹͯ͠΄͍͠ʂ(ຊAndroidαϙʔτͯ͠΄͍͚͠Ͳ᩵ݴ͍·ͤΜ) ɹɹɾHTML /
CSS / JSΛexport͢Δػೳཉ͍͠ IUUQTqVUUFSEFWEPDTEFWFMPQNFOUUPPMTEFWUPPMTJOTQFDUPS
·ͱΊ
·ͱΊ • Flutter͔ͳΓΑ͘Ͱ͖͍ͯͯɺ࣮༻తɻ • ݱঢ়ͰSwiftUI/UIKitΑΓ"ѹత"ʹ շదʹॻ͚Δɻ • ͰSwiftࣗମSwiftUIͷઃܭັྗతʂ • ͜Ε͔Β࢝·ΔWWDCͰͷSwiftUIͷਐԽʹظ