Slide 1

Slide 1 text

YUMEMI.grow Mobile #4 YUMEMI.grow Mobile #4 WWDC 2023 ݱ஍ࢀՃใࠂ ʢίʔυฤʣ 2023-06-21

Slide 2

Slide 2 text

YUMEMI.grow Mobile #4 ࣗݾ঺հ ੁݪ ༞ Twitter: @yusuga_ גࣜձࣾΏΊΈ: iOSςοΫϦʔυ ߹ಉձࣾϐίε: ୅දࣾһ

Slide 3

Slide 3 text

YUMEMI.grow Mobile #4 WWDC 2023 ॳݱ஍ࢀઓϨϙʔτ 特に気になった技術ネタを中心にお話 しします。 – NDA に配慮して現時点での公開情報の みでお届けします。 –

Slide 4

Slide 4 text

YUMEMI.grow Mobile #4 Vision Pro

Slide 5

Slide 5 text

YUMEMI.grow Mobile #4 Widgets

Slide 6

Slide 6 text

YUMEMI.grow Mobile #4 Widgetsͷର৅ൣғ֦େ 1 画像引用元: 1. Bring widgets to new places

Slide 7

Slide 7 text

YUMEMI.grow Mobile #4 Widgetsͷର৅ൣғ֦େ ・iOS 14 でホーム画面に追加 ・iOS 16 でロック画面に追加 ・iOS 17 から新たに4箇所に追加 1. macOS ͷσεΫτοϓ 2. iPad ͷϩοΫը໘ 3. iOS ͷελϯόΠϞʔυ 4. Apple Watch ͷ৽͍͠εϚʔτελ οΫ 1 画像引用元: 1. Bring widgets to new places

Slide 8

Slide 8 text

YUMEMI.grow Mobile #4 iOS 17 ͔ΒΠϯλϥΫςΟϒʹ ・直接操作可能 ・アニメーション可能 1 画像引用元: 1. WWDC 2023 Keynote

Slide 9

Slide 9 text

YUMEMI.grow Mobile #4 ࠓޙ visionOS ʹ΋΢ΟδΣοτʁ 1 画像引用元: 1. WWDC 2023 Keynote

Slide 10

Slide 10 text

YUMEMI.grow Mobile #4 Widgets ͷར༻཰ 日経電子版アプリでは、とある30日の計測で Widgets を配置している ユーザが17.6 %だった 1 引用元 1. 【NIKKEI Tech Talk #8: 3 年間にわたる iOS Widgets の開発と、その旨み/#nikkei_tech_talk

Slide 11

Slide 11 text

YUMEMI.grow Mobile #4 Swift Macros

Slide 12

Slide 12 text

YUMEMI.grow Mobile #4 Swift Macros #define SWAP(a, b) { int temp = a; a = b; b = temp; } int x = 10; int y = 20; SWAP(x, y); マクロと言えば C/C++ のつらみを思い出す – 単純な文字列の置換か連結するだけなため、濫用するとバグの温床に –

Slide 13

Slide 13 text

YUMEMI.grow Mobile #4 Swift Macros Swift のマクロは AST(Abstract Syntax Tree) を元に したコード生成ができる – ASTとは、Swiftのソースコードを解析して表現されるデ ータ構造 – マクロは2種類 – Freestanding Macros 1. Attached Macros 2.

Slide 14

Slide 14 text

YUMEMI.grow Mobile #4 Freestanding Macros func myFunction() { print("Currently running \(#function)") #warning("Something's wrong") } 1 # から始まる – #function – 現在の関数の名前が返る – #warning – コンパイル時に マクロを呼び出し、警告を生成する – warning(_:) コードの引用元: 1. The Swift Programming Language (5.9 beta)/Macros

Slide 15

Slide 15 text

YUMEMI.grow Mobile #4 Freestanding Macros ͕΍ͬͯΔ͜ͱ 値を生成する – コンパイル時に何かをする –

Slide 16

Slide 16 text

YUMEMI.grow Mobile #4 Attached Macros @OptionSet struct SundaeToppings { private enum Options: Int { case nuts case cherry case fudge } } 1 @OptionSet がマクロ – @ から始まるので見た目は Property Wrapper と同じ – コードの引用元: 1. The Swift Programming Language (5.9 beta)/Macros

Slide 17

Slide 17 text

YUMEMI.grow Mobile #4 ैདྷͷ࣮૷ struct ShippingOptions: OptionSet { let rawValue: Int static let nextDay = ShippingOptions(rawValue: 1 << 0) static let secondDay = ShippingOptions(rawValue: 1 << 1) static let priority = ShippingOptions(rawValue: 1 << 2) static let standard = ShippingOptions(rawValue: 1 << 3) static let express: ShippingOptions = [.nextDay, .secondDay] static let all: ShippingOptions = [.express, .priority, .standard] } 1 コードの引用元: 1. Documentation/Swift/Swift Standard Library/Collections/OptionSet

Slide 18

Slide 18 text

YUMEMI.grow Mobile #4 Attached Macros ͷల։લ @OptionSet struct SundaeToppings { private enum Options: Int { case nuts case cherry case fudge } } 1 コードの引用元: 1. The Swift Programming Language (5.9 beta)/Macros

Slide 19

Slide 19 text

YUMEMI.grow Mobile #4 Attached Macros ͷల։ޙ @OptionSet struct SundaeToppings { private enum Options: Int { case nuts case cherry case fudge } // Begin expansion for "@OptionSet" typealias RawValue = Int var rawValue: RawValue init() { self.rawValue = 0 } init(rawValue: RawValue) { self.rawValue = rawValue } static let nuts: Self = Self(rawValue: 1 << Options.nuts.rawValue) static let cherry: Self = Self(rawValue: 1 << Options.cherry.rawValue) static let fudge: Self = Self(rawValue: 1 << Options.fudge.rawValue) } extension SundaeToppings: OptionSet { } // End expansion for "@OptionSet" 1 コードの引用元: 1. The Swift Programming Language (5.9 beta)/Macros

Slide 20

Slide 20 text

YUMEMI.grow Mobile #4 Swift Macros ͷײ૝ Property Wrapper という黒魔術の改善 – Swift Macros は生成されたコードが展開可能で、黒魔術の中身を見せてくれる – Apple はプログラマが自前で書くコード量を削減する方向性に向かっている – 自身でコードを書かない方が楽だしバグが減るという思想 – 便利な反面、1行に多くの意味が込められるようになり、複雑さと学習コストが 高くなる – マクロの自前実装は、さらに別の複雑さが発生する可能性があるので要検討 –

Slide 21

Slide 21 text

YUMEMI.grow Mobile #4 SwiftData

Slide 22

Slide 22 text

YUMEMI.grow Mobile #4 SwiftData 待望の Core Data のラッパーFramework – Core Data は Core と付くだけあって低レイ ヤー気味で難解だった – 近年も使いやすくなるよう改良はされていた が、導入コストはまだ高かった –

Slide 23

Slide 23 text

YUMEMI.grow Mobile #4 Core Data ͸ߴػೳ 一般的な RDB と同等と考えて良い – 保存するストアが選べる – SQLite / inMemory / xml / binary – NSFetchRequest で SQL でできることはほぼ可能 – Delete Rule – Undo/Redo – iCloud同期 –

Slide 24

Slide 24 text

YUMEMI.grow Mobile #4 Schema ఆٛ @Model // Attached Macros final class Trip { @Attribute(.unique) var name: String // Attached Macros var destination: String @Relationship(.cascade) // Attached Macros var bucketList: [BucketListItem]? = [] @Relationship(.cascade) // Attached Macros var livingAccommodation: LivingAccommodation? } 1 コードの引用元: 1. Model your schema with SwiftData

Slide 25

Slide 25 text

YUMEMI.grow Mobile #4 ModelContainer スキーマとストレージの設定を行うオブジェクト – 対象のスキーマ – 自動保存するか – Undo可能にするか – 保存するストアは inMemory と SQLite のみをサポー ト –

Slide 26

Slide 26 text

YUMEMI.grow Mobile #4 ModelContainer @main struct TripsApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer(ɹ// ← ͜͜ for: [Trip.self, LivingAccommodation.self] ) } } 1 コードの引用元: 1. Meet SwiftData

Slide 27

Slide 27 text

YUMEMI.grow Mobile #4 ModelContext モデルの取得、追加、削除を行うオブ ジェクト –

Slide 28

Slide 28 text

YUMEMI.grow Mobile #4 ModelContext struct ContextView : View { @Environment(\.modelContext) private var context } 1 コードの引用元: 1. Meet SwiftData

Slide 29

Slide 29 text

YUMEMI.grow Mobile #4 Ϟσϧͷ Fetch let today = Date() let tripPredicate = #Predicate { // Freestanding Macros $0.destination == "New York" && $0.name.contains("birthday") && $0.startDate > today } let descriptor = FetchDescriptor(predicate: tripPredicate) let trips = try context.fetch(descriptor) 1 コードの引用元: 1. Meet SwiftData

Slide 30

Slide 30 text

YUMEMI.grow Mobile #4 Ϟσϧͷ௥Ճͱ࡟আ var myTrip = Trip( name: "Birthday Trip", destination: "New York" ) // Insert a new trip context.insert(myTrip) // Delete an existing trip context.delete(myTrip) // Manually save changes to the context try context.save() 1 コードの引用元: 1. Meet SwiftData

Slide 31

Slide 31 text

YUMEMI.grow Mobile #4 SwiftData ͷײ૝ とうとう Core Data がお手軽に使えるか!?(iOS 3からある) – Core Data から SwiftData へのマイグレーションも考慮された設計 (併用も可能) – ただし、パフォーマンス面での懸念がある – 少なくとも2015年(iOS 9)時点では Core Data は 1万件を超える データを扱うべきではないとドキュメントに明記されていた記憶 – 今は端末スペックも上がってるし大丈夫かな…? –

Slide 32

Slide 32 text

YUMEMI.grow Mobile #4 ͦͷଞʹؾʹͳΔ࿩୊ @Observable – String Catalog – Mergeable Libraries – Swift OpenAPI Generator – Human Interface Guidelines の日本語化 –

Slide 33

Slide 33 text

YUMEMI.grow Mobile #4 ·ͱΊ Vision Pro の実物が見れて購買意欲が湧いた – Apple のエンジニアに直接質問できたのも良かった – ゆめみは WWDC の旅費交通費を全額会社負担 しま す! – 1 一応注釈で2023年6月時点と記載しますが、2017年から全額会社負担をしています。 1.

Slide 34

Slide 34 text

YUMEMI.grow Mobile #4 ͝੩ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ