Slide 1

Slide 1 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. #iosdc #b 1 #iosdc #b iOSDC Japan 2025 Day 1 treastrain / Tanaka Ryoga ͦΖͦΖ FormatStyle

Slide 2

Slide 2 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 2 treastrain / Tanaka Ryoga @treastrainɹhttps://tret.jp Swift 🦅 / Core NFC 📶 - Japan NFC Reader 💳 - PadDisplay 📺 - XCIntelligenceBridge 🌉 DeNA Co., Ltd. - iOS App Developer ( April 2021 - Current)

Slide 3

Slide 3 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 3

Slide 4

Slide 4 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 4

Slide 5

Slide 5 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 5

Slide 6

Slide 6 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 6

Slide 7

Slide 7 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 7

Slide 8

Slide 8 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 8

Slide 9

Slide 9 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. FormatStyle 9

Slide 10

Slide 10 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 10 FormatStyle | Apple Developer Documentation https://developer.apple.com/documentation/foundation/formatstyle

Slide 11

Slide 11 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. What’s new for Apple developers - Apple Developer https://developer.apple.com/whats-new/ iOS 15 ( 2021 ) iOS 16 ( 2022 ) iOS 17 ( 2023 ) iOS 18 ( 2024 ) iOS 26 ( 2025 ) 11

Slide 12

Slide 12 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 12 App Store - αϙʔτ - Apple Developer https://developer.apple.com/jp/support/app-store/

Slide 13

Slide 13 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 13 App Store - αϙʔτ - Apple Developer https://developer.apple.com/jp/support/app-store/

Slide 14

Slide 14 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ͦΖͦΖ FormatStyle • ʮσʔλͷϑΥʔϚοτʯʹ͍ͭͯ͜Ε͔ΒֶͿํ • ैདྷͷ Formatter ͸࢖ͬͨ͜ͱ͕͋Γɺ ৽͍͠ FormatStyle ʹ׳Ε͍ͯͳ͍ํ • ಠࣗͷ FormatStyle ͷ࡞ΓํͷαϯϓϧΛ஌Γ͍ͨํ 14

Slide 15

Slide 15 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. σʔλͷϑΥʔϚοτ 15

Slide 16

Slide 16 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 16

Slide 17

Slide 17 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. import SwiftUI struct ContentView: View { var body: some View { VStack { Text("ͦΖͦΖ FormatStyle") Text("2025೥9݄20೔ 13:00") } } } 17

Slide 18

Slide 18 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. struct ContentView: View { var title: String var date: String var body: some View { VStack { Text(title) Text(date) } } } 18

Slide 19

Slide 19 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date) } } } 19

Slide 20

Slide 20 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date) } } } 20 􀒊 Initializer 'init(_:)' requires that 'Date' conform to 'StringProtocol'

Slide 21

Slide 21 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 21 Date String

Slide 22

Slide 22 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 22 Date String

Slide 23

Slide 23 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 23 import Foundation let date: Date = ... let seconds: Double = date.timeIntervalSinceReferenceDate

Slide 24

Slide 24 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 24 import Foundation let date: Date = ... let seconds: Double = date.timeIntervalSinceReferenceDate 780033600.0

Slide 25

Slide 25 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 25 2025೥9݄20೔ 13 : 00 780033600.0

Slide 26

Slide 26 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 26 780033600.0 ྩ࿨7೥9݄20೔ 13 : 00

Slide 27

Slide 27 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 27 780033600.0 September 20, 2025 at 1 : 00 PM

Slide 28

Slide 28 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 28

Slide 29

Slide 29 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 29

Slide 30

Slide 30 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 30

Slide 31

Slide 31 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 31 Data Formatting | Apple Developer Documentation https://developer.apple.com/documentation/foundation/data-formatting

Slide 32

Slide 32 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ͜Ε·Ͱͷ Formatter 32

Slide 33

Slide 33 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 33

Slide 34

Slide 34 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 34

Slide 35

Slide 35 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 35

Slide 36

Slide 36 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 36

Slide 37

Slide 37 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 37

Slide 38

Slide 38 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 38

Slide 39

Slide 39 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 39 NSFormatter | Apple Developer Documentation https://developer.apple.com/documentation/foundation/formatter

Slide 40

Slide 40 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Objective-C ͷ࣌୅͔Βଘࡏ͢Δ NSFormatter 40 NSDateFormatterɹNSDateIntervalFormatterɹ NSISO8601DateFormatterɹNSRelativeDateTimeFormatterɹ NSDateComponentsFormatterɹNSNumberFormatterɹ NSByteCountFormatterDateFormatterɹ NSPersonNameComponentsFormatterɹ NSMeasurementFormatterɹNSEnergyFormatterɹ NSLengthFormatterɹNSMassFormatterɹNSListFormatter

Slide 41

Slide 41 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Swift ͔Β Objective-C ͷࢿ࢈Λ࢖͏ SE - 0086 Drop NS Prefix in Swift Foundation 41 DateFormatterɹDateIntervalFormatterɹ ISO8601DateFormatterɹRelativeDateTimeFormatterɹ DateComponentsFormatterɹNumberFormatterɹ ByteCountFormatterDateFormatterɹ PersonNameComponentsFormatterɹ MeasurementFormatterɹEnergyFormatterɹ LengthFormatterɹMassFormatterɹListFormatter

Slide 42

Slide 42 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 42 Formatter | Apple Developer Documentation https://developer.apple.com/documentation/foundation/formatter

Slide 43

Slide 43 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 43 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ

Slide 44

Slide 44 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 44 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateStyle = .long formatter.timeStyle = .short

Slide 45

Slide 45 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 45 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateStyle = .long formatter.timeStyle = .short let formattedDate: String = formatter.string(from: date) // 2024೥12݄31೔ 23:59

Slide 46

Slide 46 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 46 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateStyle = .long formatter.timeStyle = .none let formattedDate: String = formatter.string(from: date) // 2024೥12݄31೔

Slide 47

Slide 47 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 47 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateFormat = "Y೥M݄"

Slide 48

Slide 48 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 48 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateFormat = "Y೥M݄" let formattedDate: String = formatter.string(from: date) // 2025೥12݄ 😔

Slide 49

Slide 49 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 49 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateFormat = "Y೥M݄" let formattedDate: String = formatter.string(from: date) // 2025೥12݄ 😔 Unicode Locale Data Markup Language (LDML)

Slide 50

Slide 50 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 50 Unicode Locale Data Markup Language ( LDML ) Part 4 : Dates https://unicode.org/reports/tr35/tr35-dates.html

Slide 51

Slide 51 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 51 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateFormat = "Y೥M݄" let formattedDate: String = formatter.string(from: date) // 2025೥12݄

Slide 52

Slide 52 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 52 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateFormat = "y೥M݄" let formattedDate: String = formatter.string(from: date) // 2024೥12݄

Slide 53

Slide 53 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 53 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateFormat = "y೥M݄" let formattedDate: String = formatter.string(from: date) // 2024೥12݄ December 2024...?

Slide 54

Slide 54 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 54 import Foundation let date = Date(timeIntervalSinceReferenceDate: 757349999) // 2024೥12݄31೔ 23:59:59ʢ೔ຊ࣌ؒʣ let formatter = DateFormatter() formatter.dateFormat = "y೥M݄" let formattedDate: String = formatter.string(from: date) // 2024೥12݄

Slide 55

Slide 55 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 55 FormattersɿσʔλΛώϡʔϚϯϑϨϯυϦʔʹ - WWDC20 - ϏσΦ - Apple Developer https://developer.apple.com/jp/videos/play/wwdc2020/10160/

Slide 56

Slide 56 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 56 FormattersɿσʔλΛώϡʔϚϯϑϨϯυϦʔʹ - WWDC20 - ϏσΦ - Apple Developer https://developer.apple.com/jp/videos/play/wwdc2020/10160/

Slide 57

Slide 57 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 57 formatter.dateFormat = "y೥M݄"

Slide 58

Slide 58 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 58

Slide 59

Slide 59 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 59

Slide 60

Slide 60 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 60

Slide 61

Slide 61 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 61

Slide 62

Slide 62 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 62 InstrumentsʹΑΔSwiftUIͷύϑΥʔϚϯε࠷దԽ - WWDC25 - ϏσΦ - Apple Developer https://developer.apple.com/jp/videos/play/wwdc2025/306/

Slide 63

Slide 63 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 63 InstrumentsʹΑΔSwiftUIͷύϑΥʔϚϯε࠷దԽ - WWDC25 - ϏσΦ - Apple Developer https://developer.apple.com/jp/videos/play/wwdc2025/306/

Slide 64

Slide 64 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 64

Slide 65

Slide 65 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 65

Slide 66

Slide 66 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ͜Ε·Ͱͷ Formatter Swift ͔Β࢖͏ͱ͖ʹؾΛ͚ͭΔ͜ͱ • จࣈྻʹΑΔϑΥʔϚοτܗࣜͷࢦఆ͕ՄೳɺίϯύΠϧ࣌ʹݕূ͞Εͳ͍ • Formatter ͷΠϯελϯεͷੜ੒ɾϓϩύςΟͷมߋͷίετ͕ߴ͍ • Πϯελϯεੜ੒ɾϓϩύςΟมߋͷճ਺ΛݮΒͨ͢Ίʹ ΩϟογϡΛҙࣝͨ͠Γɺࣗ෼ͰͦͷͨΊͷ࣮૷Λͨ͠Γ͢Δඞཁ • ΫϥεʢࢀরܕʣͰ͋Δ • ໋ྩܕͷ API σβΠϯ 66

Slide 67

Slide 67 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ͜Ε͔Βͷ FormatStyle 67

Slide 68

Slide 68 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 68 FormatStyle | Apple Developer Documentation https://developer.apple.com/documentation/foundation/formatstyle

Slide 69

Slide 69 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 69 nentsFormatStyleɹIntegerFormatStyle.CurrencyɹStringStyleɹDecimal.FormatStyl ateOffsetɹDuration.TimeFormatStyleɹDate.AttributedStyleɹMeasurement.Attribu FormatStyleɹSystemFormatStyle.DateReferenceɹDateComponents.HTTPFormatSt utedɹListFormatStyleɹMeasurement.FormatStyle.ByteCountɹDate.IntervalForma ributedɹDecimal.FormatStyleɹDate.ISO8601FormatStyleɹIntegerFormatStyle.Per edɹURL.FormatStyleɹDate.FormatStyle.AttributedɹDate.RelativeFormatStyleɹFlo tɹDate.VerbatimFormatStyle.AttributedɹPersonNameComponents.FormatStyleɹD yɹDecimal.FormatStyle.CurrencyɹIntegerFormatStyleɹMeasurement.AttributedS atchɹDuration.UnitsFormatStyleɹPersonNameComponents.AttributedStyleɹInteg horedRelativeFormatStyleɹByteCountFormatStyleɹDateComponents.ISO8601Form

Slide 70

Slide 70 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 70 struct ContentView: View { var title: String var date: Date private var formattedDate: String { let formatter = DateFormatter() formatter.dateStyle = .long formatter.timeStyle = .short return formatter.string(from: date) } var body: some View { VStack { Text(title) Text(formattedDate) } } }

Slide 71

Slide 71 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 71 struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date.formatted()) } } }

Slide 72

Slide 72 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 72 struct ContentView: View { var title: String var date: Date private var formattedDate: String { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .none return formatter.string(from: date) } var body: some View { VStack { Text(title) Text(formattedDate) } } } struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date.formatted()) } } }

Slide 73

Slide 73 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 73 struct ContentView: View { var title: String var date: Date private var formattedDate: String { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .none return formatter.string(from: date) } var body: some View { VStack { Text(title) Text(formattedDate) } } } struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date.formatted()) } } }

Slide 74

Slide 74 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 74 struct ContentView: View { var title: String var date: Date private var formattedDate: String { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .none return formatter.string(from: date) } var body: some View { VStack { Text(title) Text(formattedDate) } } } struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date.formatted()) } } }

Slide 75

Slide 75 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 75 struct ContentView: View { var title: String var date: Date private var formattedDate: String { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .none return formatter.string(from: date) } var body: some View { VStack { Text(title) Text(formattedDate) } } } struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date.formatted( Date.FormatStyle( date: .abbreviated, time: .omitted ) )) } } }

Slide 76

Slide 76 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 76 let formatter = DateFormatter() formatter.dateFormat = "y೥M݄" formatter.string(from: date) // 2024೥12݄ date.formatted( .dateTime .year().month() ) // 2024೥12݄

Slide 77

Slide 77 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Formatter FormatStyle 77 Objective-Cϕʔε Ϋϥεʢࢀরܕʣ ॊೈͳελΠϧࢦఆ खಈͰΩϟογϡ؅ཧ ໋ྩܕͷΠϯλʔϑΣΠε Swiftϕʔε ߏ଄ମʢ஋ܕʣ ܕ҆શͳελΠϧࢦఆ ಺෦ͷࣗಈΩϟογϡ એݴܕͷΠϯλʔϑΣΠε

Slide 78

Slide 78 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 78 FormatStyle | Apple Developer Documentation https://developer.apple.com/documentation/foundation/formatstyle

Slide 79

Slide 79 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 79 @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol FormatStyle< FormatInput, FormatOutput > : Decodable, Encodable, Hashable { associatedtype FormatInput associatedtype FormatOutput func format(_ value: Self.FormatInput) -> Self.FormatOutput func locale(_ locale: Locale) -> Self }

Slide 80

Slide 80 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 80 @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol FormatStyle< FormatInput, FormatOutput > : Decodable, Encodable, Hashable { associatedtype FormatInput associatedtype FormatOutput func format(_ value: Self.FormatInput) -> Self.FormatOutput func locale(_ locale: Locale) -> Self }

Slide 81

Slide 81 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 81 @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol FormatStyle< FormatInput, FormatOutput > : Decodable, Encodable, Hashable { associatedtype FormatInput associatedtype FormatOutput func format(_ value: Self.FormatInput) -> Self.FormatOutput func locale(_ locale: Locale) -> Self }

Slide 82

Slide 82 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 82 @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol FormatStyle< FormatInput, FormatOutput > : Decodable, Encodable, Hashable { associatedtype FormatInput associatedtype FormatOutput func format(_ value: Self.FormatInput) -> Self.FormatOutput func locale(_ locale: Locale) -> Self }

Slide 83

Slide 83 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 83 Date String

Slide 84

Slide 84 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 84 @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol FormatStyle< FormatInput, FormatOutput > : Decodable, Encodable, Hashable { associatedtype FormatInput associatedtype FormatOutput func format(_ value: Self.FormatInput) -> Self.FormatOutput func locale(_ locale: Locale) -> Self } Date String

Slide 85

Slide 85 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ͢΂ͯͷ FormatStyle 85

Slide 86

Slide 86 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ͢΂ͯͷ FormatStyle iOS 26 ·Ͱʹ౥ࡌ͞Ε͍ͯΔ΋ͷ͢΂ͯ • SwiftɺFoundationɺStoreKit ʹ͋Δ 29 छྨ͢΂ͯ • ͢΂ͯΛҰ౓ʹ֮͑Δʹ͸਺͕ଟ͍ • ެ։ࢿྉ΍ΞʔΧΠϒͰͷৼΓฦΓͷ͖͔͚ͬʹͳΕ͹ • ೖྗଆͷܕɺग़ྗଆͷܕΛ͜ͷΑ͏ʹࣔ͠·͢ 86 String Date

Slide 87

Slide 87 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ೔෇ɾ࣌ࠁɾظؒͷ FormatStyle 87 Date DateComponents Range

Slide 88

Slide 88 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.FormatStyle 88 String Date let date = Date.now // 2025/9/20 13:00 date.formatted() // 2025೥9݄20೔ ౔༵೔ 13:00:00 date.formatted(date: .complete, time: .standard)

Slide 89

Slide 89 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.FormatStyle 89 String Date let date = Date.now // 2025೥9݄20೔ date.formatted(.dateTime.month().day().year()) // 2025/09/20 date.formatted(.dateTime.year().month(.twoDigits).day(.twoDigits))

Slide 90

Slide 90 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.ISO8601FormatStyle 90 String Date let date = Date.now // 2025-09-20T04:00:00Z date.formatted(.iso8601) // 20250920T04:00:00Z date.formatted(.iso8601.dateSeparator(.omitted))

Slide 91

Slide 91 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.ISO8601FormatStyle 91 String Date let date = Date.now // 2025-09-20T13:00:00+0900 date.formatted(Date.ISO8601FormatStyle( timeZone: TimeZone(identifier: "Asia/Tokyo")! )) // 2025-09-20T04:00:00.000Z date.formatted(.iso8601.year().month().day() .time(includingFractionalSeconds: true) .timeZone(separator: .colon))

Slide 92

Slide 92 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. DateComponents.ISO8601FormatStyle 92 String DateComponents let components: DateComponents = ... // 2025-09-20T04:00:00Z components.formatted(.iso8601) // 20250920T04:00:00Z components.formatted(.iso8601.dateSeparator(.omitted)) // 2025-09-20T04:00:00.000Z components.formatted(.iso8601.year().month().day() .time(includingFractionalSeconds: true) .timeZone(separator: .colon))

Slide 93

Slide 93 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.HTTPFormatStyle 93 String Date let date = Date.now // Sat, 20 Sep 2025 04:00:00 GMT date.formatted(.http)

Slide 94

Slide 94 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. DateComponents.HTTPFormatStyle 94 String DateComponents let components: DateComponents = ... // Sat, 20 Sep 2025 04:00:00 GMT components.formatted(.http)

Slide 95

Slide 95 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.VerbatimFormatStyle 95 String Date let date = Date.now // JIS X 0301 Ͱ͸ // ʮ೥߸ʢ1จࣈʣͱ೥ͷ਺ࣈ2ܻʯʮ݄ͷ਺ࣈ2ܻʯʮ೔ͷ਺ࣈ2ܻʯΛϐϦΦυͰܨ͙ let jisX0301Format: Date.FormatString = "\(era: .narrow)\(year: .twoDigits) .\(month: .twoDigits) .\(day: .twoDigits)"

Slide 96

Slide 96 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.VerbatimFormatStyle 96 String Date let date = Date.now let jisX0301Format: Date.FormatString = ... // R07.09.20 date.formatted(.verbatim( jisX0301Format, locale: Locale(languageCode: .japanese, languageRegion: .japan), timeZone: TimeZone(identifier: "Asia/Tokyo")!, calendar: Calendar(identifier: .japanese) ))

Slide 97

Slide 97 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.IntervalFormatStyle 97 String Range let startDate = ... // 2025೥9݄19೔ 16:00 let endDate = ... // 2025೥9݄21೔ 18:00 let iosdcJapan2025: Range = startDate..

Slide 98

Slide 98 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.ComponentsFormatStyle 98 String Range let iosdcJapan2025: Range = startDate..

Slide 99

Slide 99 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.RelativeFormatStyle 99 String Date let lastMonth: Date = ... lastMonth.formatted(.relative(presentation: .named)) // དྷ݄ let nextMonth: Date = ... nextMonth.formatted(.relative(presentation: .named)) // དྷ݄ nextMonth.formatted(.relative(presentation: .numeric)) // 1 ͔݄ޙ let twoDaysAgo: Date = ... twoDaysAgo.formatted(.relative(presentation: .named)) // Ұࡢ೔ // ΞϝϦΧӳޠ؀ڥͰ͸ 2 days ago

Slide 100

Slide 100 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Date.AnchoredRelativeFormatStyle 100 String Date let lastMonth: Date = ... let nextMonth: Date = ... // 2 ͔݄લ nextMonth.formatted( Date.AnchoredRelativeFormatStyle(anchor: lastMonth) )

Slide 101

Slide 101 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ਺஋ͷ FormatStyle 101 BinaryInteger BinaryFloatingPoint Decimal

Slide 102

Slide 102 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. IntegerFormatStyle FloatingPointFormatStyle Decimal.FormatStyle 102 String BinaryInteger BinaryFloatingPoint Decimal let integer: Int = 17 let floating: Double = 6.3 let decimal: Decimal = 179800 integer.formatted() // 17 floating.formatted() // 6.3 decimal.formatted() // 179,800

Slide 103

Slide 103 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. IntegerFormatStyle FloatingPointFormatStyle Decimal.FormatStyle 103 String BinaryInteger BinaryFloatingPoint Decimal let integer: Int = 17 let floating: Double = 6.3 let decimal: Decimal = 179800 integer.formatted(.number.rounded(increment: 10)) // 20 floating.formatted(.number.scale(10)) // 63 decimal.formatted(.number.notation(.compactName)) // 18ສ // ΞϝϦΧӳޠ؀ڥͰ͸ 180K

Slide 104

Slide 104 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. IntegerFormatStyle.Percent FloatingPointFormatStyle.Percent Decimal.FormatStyle.Percent 104 String BinaryInteger BinaryFloatingPoint Decimal let number = 0.75 number.formatted(.percent) // ೔ຊͷ೔ຊޠ؀ڥͰ͸ 75% // ΤδϓτͷΞϥϏΞޠ؀ڥͰ͸ ٪٧٥ number.formatted(.percent.rounded(increment: 10)) // 80%

Slide 105

Slide 105 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. IntegerFormatStyle.Currency FloatingPointFormatStyle.Currency Decimal.FormatStyle.Currency 105 String BinaryInteger BinaryFloatingPoint Decimal let japaneseYen = 159800 let canadianDollars = 1449 japaneseYen.formatted(.currency(code: "JPY")) // ೔ຊͷ೔ຊޠ؀ڥͩͱ ¥159,800 canadianDollars.formatted(.currency(code: "CAD")) // Χφμͷӳޠ؀ڥͩͱ $1,449.00 ϑϥϯεޠ؀ڥͩͱ 1 449,00 $

Slide 106

Slide 106 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ࣌ؒͷ FormatStyle 106 Duration

Slide 107

Slide 107 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Duration.TimeFormatStyle 107 String Duration let duration = Duration.seconds(40 * 60) duration.formatted() // 0:40:00 duration.formatted(.time(pattern: .minuteSecond)) // 40:00

Slide 108

Slide 108 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Duration.TimeFormatStyle 108 String Duration let duration = Duration.milliseconds(500) duration.formatted() // 0:00:00 duration.formatted(.time(pattern: .hourMinuteSecond(padHourToLength: 0, fractionalSecondsLength: 2) )) // 0:00:00.50

Slide 109

Slide 109 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Duration.UnitsFormatStyle 109 String Duration let duration = Duration.seconds(40 * 60) duration.formatted(.units()) // 40෼ duration.formatted(.units( allowed: [.minutes, .seconds], zeroValueUnits: .show(length: 2) )) // 40෼ 00ඵ

Slide 110

Slide 110 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ܭଌ஋ͷ FormatStyle 110 Measurement Int64 Measurement

Slide 111

Slide 111 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Measurement ܭଌ஋ • ໘ੵɹUnitArea • ௕͞ɹUnitLength • ମੵɹUnitVolume • ֯౓ɹUnitAngle • ॏ͞ɹUnitMass • ѹྗɹUnitPressure • Ճ଎౓ɹUnitAcceleration • ܧଓ࣌ؒɹUnitDuration • प೾਺ɹUnitFrequency • ଎͞ɹUnitSpeed • ΤωϧΪʔɹUnitEnergy • ిྗɹUnitPower • Թ౓ɹUnitTemperature • র౓ɹUnitIlluminance • ిՙɹUnitElectricCharge • ిྲྀɹUnitElectricCurrent • ిѹɹUnitElectricPotentialDifference • ిؾ఍߅ɹUnitElectricResistance • ࣭ྔೱ౓ɹUnitConcentrationMass • ෼ࢄɹUnitDispersion • ೩අɹUnitFuelEfficiency • ৘ใྔɹUnitInformationStorage 111

Slide 112

Slide 112 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Measurement ܭଌ஋ 112 let aomori: Double = 9646 let akita: Double = 11638 let iwate: Double = 15275

Slide 113

Slide 113 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Measurement ܭଌ஋ 113 let aomori = Measurement(value: 9646, unit: UnitArea.squareKilometers) let akita = Measurement(value: 11638, unit: UnitArea.squareKilometers) let iwate = Measurement(value: 15275, unit: UnitArea.squareKilometers)

Slide 114

Slide 114 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Measurement.FormatStyle 114 String Measurement let aomori = Measurement(value: 9646, unit: UnitArea.squareKilometers) let akita = Measurement(value: 11638, unit: UnitArea.squareKilometers) let iwate = Measurement(value: 15275, unit: UnitArea.squareKilometers) aomori.formatted() // 9,646 km² akita.formatted(.measurement(width: .wide)) // 11,638ฏํΩϩϝʔτϧ iwate.formatted(.measurement(width: .abbreviated) .locale(Locale( languageCode: .english, languageRegion: .unitedStates)) ) // 5,898 sq mi

Slide 115

Slide 115 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ByteCountFormatStyle Measurement.FormatStyle.ByteCount 115 String Int64 Measurement let xcode26 = 8552433052 // 8.55 GB xcode26.formatted(.byteCount(style: .file)) // 8,552.4 MB xcode26.formatted(.byteCount(style: .file, allowedUnits: .mb))

Slide 116

Slide 116 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ਓͷ໊લͷ FormatStyle 116 PersonNameComponents

Slide 117

Slide 117 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. PersonNameComponents.FormatStyle 117 String PersonNameComponents var compontents = PersonNameComponents() compontents.familyName = "ͨͳ͔" compontents.givenName = "Γΐ͏͕" compontents.nickname = "treastrain"

Slide 118

Slide 118 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. PersonNameComponents.FormatStyle 118 String PersonNameComponents compontents.formatted() // ͨͳ͔Γΐ͏͕ compontents.formatted(.name(style: .medium) .locale(Locale(languageRegion: .unitedStates)) ) // ͨͳ͔Γΐ͏͕ compontents.formatted(.name(style: .short)) // treastrain compontents.formatted(.name(style: .abbreviated)) // treastrain

Slide 119

Slide 119 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. PersonNameComponents.FormatStyle 119 String PersonNameComponents var compontents = PersonNameComponents() compontents.familyName = "Tanaka" compontents.givenName = "Ryoga" compontents.nickname = "treastrain"

Slide 120

Slide 120 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. PersonNameComponents.FormatStyle 120 String PersonNameComponents compontents.formatted() // Tanaka Ryoga compontents.formatted(.name(style: .medium) .locale(Locale(languageRegion: .unitedStates)) ) // Ryoga Tanaka compontents.formatted(.name(style: .short)) // treastrain compontents.formatted(.name(style: .abbreviated)) // TR compontents.formatted(.name(style: .abbreviated) .locale(Locale(languageRegion: .unitedStates)) ) // RT

Slide 121

Slide 121 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. URL ͷ FormatStyle 121 URL

Slide 122

Slide 122 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. URL.FormatStyle 122 String URL let url = URL(string: "https://www.example.com:8080/path/to/endpoint?key=value")! url.formatted() // https://www.example.com/path/to/endpoint let url = URL(string: "https://example.com/endpoint?key1=value1&key2=value2")! url.formatted( .url.scheme(.never).host(.never).path(.never).query(.always) ) // ?key1=value1&key2=value2

Slide 123

Slide 123 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. URL.FormatStyle 123 String URL let url = URL(string: "https://www.example.com:8080/path/to/endpoint")! url.formatted(.url.scheme(.never).path(.never)) // www.example.com let abunaiURL = URL(string: "https://example.comΜexampleΜ.example.com/path/to/endpoint")! url.formatted(.url.scheme(.never).path(.never)) // example.comΜexampleΜ.example.com

Slide 124

Slide 124 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ͦͷ΄͔ͷ FormatStyle 124 String Sequence Product.SubscriptionPeriod.Unit

Slide 125

Slide 125 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ListFormatStyle 125 String Sequence let ϑϧʔπ = ["ΓΜ͝", "όφφ", "Έ͔Μ"] ϑϧʔπ.formatted() // ΓΜ͝ɺόφφɺΈ͔Μ ϑϧʔπ.formatted(.list(type: .or)) // ΓΜ͝ɺόφφɺ·ͨ͸Έ͔Μ // ΞϝϦΧӳޠ؀ڥͰ͸ let fruits = ["Apple", "Banana", "Orange"] fruits.formatted() // Apple, Banana, and Orange fruits.formatted( .list(type: .and, width: .short)) // Apple, Banana, & Orange

Slide 126

Slide 126 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ListFormatStyle 126 String Sequence let numbers = [1, 10, 100, 1000] numbers.formatted(.list(memberStyle: .number, type: .and)) // 1ɺ10ɺ100ɺ1,000

Slide 127

Slide 127 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. StringStyle 127 String String let numbers = [1, 10, 100, 1000] numbers.formatted(.list(memberStyle: .number, type: .and)) // 1ɺ10ɺ100ɺ1,000 let ϑϧʔπ = ["ΓΜ͝", "όφφ", "Έ͔Μ"] ϑϧʔπ.formatted(.list(type: .or)) // ΓΜ͝ɺόφφɺ·ͨ͸Έ͔Μ ListFormatStyle ListFormatStyle

Slide 128

Slide 128 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Product.SubscriptionPeriod.Unit.FormatStyle 128 Product.SubscriptionPeriod.Unit String import StoreKit let identifiers = [ "com.example.app.item1", // 1िؒͷࣗಈߋ৽αϒεΫϦϓγϣϯ "com.example.app.item2", // 1ϲ݄ͷࣗಈߋ৽αϒεΫϦϓγϣϯ "com.example.app.item3", // 1೥ͷࣗಈߋ৽αϒεΫϦϓγϣϯ ] for product in try await Product.products(for: identifiers) { let subscription = product.subscription! subscription.subscriptionPeriod.unit .formatted(product.subscriptionPeriodUnitFormatStyle) // ि // ݄ // ೥ }

Slide 129

Slide 129 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ͢΂ͯͷ FormatStyle iOS 26 ·Ͱʹ౥ࡌ͞Ε͍ͯΔ΋ͷ͢΂ͯ • SwiftɺFoundationɺStoreKit ʹ͋Δ 29 छྨ͢΂ͯ • ͢΂ͯΛҰ౓ʹ֮͑Δʹ͸਺͕ଟ͍ • ެ։ࢿྉ΍ΞʔΧΠϒͰৼΓฦΓʹདྷ͍ͯͩ͘͞ • ೖྗଆͷܕɺग़ྗଆͷܕΛ͜ͷΑ͏ʹࣔ͠·ͨ͠ 129 String Date

Slide 130

Slide 130 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Attribute ʹରԠͨ͠ FormatStyle 130

Slide 131

Slide 131 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 131 Date.FormatStyleɹDate.ISO8601FormatStyle Date.VerbatimFormatStyleɹDate.IntervalFormatStyle IntegerFormatStyleɹDate.ComponentsFormatStyle FloatingPointFormatStyleɹDate.RelativeFormatStyle Decimal.FormatStyleɹDate.AnchoredRelativeFormatStyle Duration.TimeFormatStyleɹDate.HTTPFormatStyle Duration.UnitsFormatStyleɹDateComponents.HTTPFormatStyle Measurement.FormatStyleɹDateComponents.ISO8601FormatStyle ByteCountFormatStyleɹIntegerFormatStyle.Percent Measurement.FormatStyle.ByteCountɹFloatingPointFormatStyle.Percent PersonNameComponents.FormatStyleɹDecimal.FormatStyle.Percent IntegerFormatStyle.CurrencyɹFloatingPointFormatStyle.Currencyɹ Decimal.FormatStyle.CurrencyɹURL.FormatStyle

Slide 132

Slide 132 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 132 Date.FormatStyle.Attributed Date.VerbatimFormatStyle.Attributed IntegerFormatStyle.Attributed FloatingPointFormatStyle.Attributed Decimal.FormatStyle.Attributed Duration.TimeFormatStyle.Attributed Duration.UnitsFormatStyle.Attributed Measurement.AttributedStyle ByteCountFormatStyle.Attributed Measurement.AttributedStyle.ByteCount PersonNameComponents.AttributedStyle

Slide 133

Slide 133 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. Attribute ʹରԠͨ͠ FormatStyle iOS 26 ·Ͱʹ౥ࡌ͞Ε͍ͯΔ΋ͷ͢΂ͯ • Date.FormatStyle • Date.VerbatimFormatStyle • IntegerFormatStyle • FloatingPointFormatStyle • Decimal.FormatStyle • Duration.TimeFormatStyle • Duration.UnitsFormatStyle • Measurement.FormatStyle • ByteCountFormatStyle • Measurement.FormatStyle.ByteCount • PersonNameComponents.FormatStyle 133 AttributedString ...

Slide 134

Slide 134 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 134 struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date.formatted( Date.FormatStyle( date: .long, time: .shortened ) )) } } }

Slide 135

Slide 135 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 135 var formattedDate: String { date.formatted( Date.FormatStyle( date: .long, time: .shortened ) ) } var body: some View { VStack { Text(title) Text(formattedDate) } }

Slide 136

Slide 136 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 136 var formattedDate: AttributedString { date.formatted( Date.FormatStyle( date: .long, time: .shortened ) .attributedStyle ) }

Slide 137

Slide 137 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 137 var formattedDate: AttributedString { var string = date.formatted( Date.FormatStyle( date: .long, time: .shortened ) .attributedStyle ) let year = AttributeContainer() .dateField(.year) let color = AttributeContainer() .foregroundColor(.red) string.replaceAttributes(year, with: color) return string }

Slide 138

Slide 138 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 138 struct ContentView: View { var price: Decimal var formattedPrice: AttributedString { var string = price.formatted( .currency(code: "JPY").attributed ) let currencySymbol = AttributeContainer() .numberSymbol(.currency) let font = AttributeContainer().font(.title) string.replaceAttributes(currencySymbol, with: font) return string } var body: some View { Text(formattedPrice).font(.largeTitle) } }

Slide 139

Slide 139 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. SwiftUI ʹ͋Δ Attributed ͳ FormatStyle iOS 18 ͔Βͷετοϓ΢Υον΍λΠϚʔͳͲͷදࣔʹಛԽ • SystemFormatStyle.DateOffset • SystemFormatStyle.DateReference • SystemFormatStyle.Stopwatch • SystemFormatStyle.Timer 139

Slide 140

Slide 140 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. SwiftUI ͔Β FormatStyle Λ࢖͏ 140

Slide 141

Slide 141 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date) } } } 141 􀒊 Initializer 'init(_:)' requires that 'Date' conform to 'StringProtocol'

Slide 142

Slide 142 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date.formatted()) } } } 142

Slide 143

Slide 143 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. struct ContentView: View { var title: String var date: Date var body: some View { VStack { Text(title) Text(date, format: .dateTime) } } } 143 􀊫 DiscreteFormatStyle

Slide 144

Slide 144 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. struct ContentView: View { var title: String var date: Date var body: some View { Text("\(title)\n\(date, format: .dateTime)") } } 144

Slide 145

Slide 145 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 145 struct ContentView: View { @State private var number = 0 var body: some View { TextField( "Input the magic number", value: $number, format: .number ) .keyboardType(.numberPad) } } String ...

Slide 146

Slide 146 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ParseableFormatStyle 146

Slide 147

Slide 147 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 147 @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol ParseableFormatStyle : FormatStyle { associatedtype Strategy : ParseStrategy where Self.FormatInput == Self.Strategy.ParseOutput, Self.FormatOutput == Self.Strategy.ParseInput var parseStrategy: Self.Strategy { get } } @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol ParseStrategy : Decodable, Encodable, Hashable { associatedtype ParseInput associatedtype ParseOutput func parse(_ value: Self.ParseInput) throws -> Self.ParseOutput }

Slide 148

Slide 148 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 148 @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol ParseableFormatStyle : FormatStyle { associatedtype Strategy : ParseStrategy where Self.FormatInput == Self.Strategy.ParseOutput, Self.FormatOutput == Self.Strategy.ParseInput var parseStrategy: Self.Strategy { get } } @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol ParseStrategy : Decodable, Encodable, Hashable { associatedtype ParseInput associatedtype ParseOutput func parse(_ value: Self.ParseInput) throws -> Self.ParseOutput }

Slide 149

Slide 149 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 149 @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol ParseableFormatStyle : FormatStyle { associatedtype Strategy : ParseStrategy where Self.FormatInput == Self.Strategy.ParseOutput, Self.FormatOutput == Self.Strategy.ParseInput var parseStrategy: Self.Strategy { get } } @available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *) public protocol ParseStrategy : Decodable, Encodable, Hashable { associatedtype ParseInput associatedtype ParseOutput func parse(_ value: Self.ParseInput) throws -> Self.ParseOutput }

Slide 150

Slide 150 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ParseableFormatStyle iOS 26 ·Ͱʹ౥ࡌ͞Ε͍ͯΔ΋ͷ͢΂ͯ • Date.FormatStyle • Date.ISO8601FormatStyle • Date.VerbatimFormatStyle • Date.HTTPFormatStyle • DateComponents.HTTPFormatStyle • DateComponents.ISO8601FormatStyle • IntegerFormatStyle • IntegerFormatStyle.Percent • IntegerFormatStyle.Currency • FloatingPointFormatStyle • FloatingPointFormatStyle.Percent • FloatingPointFormatStyle.Currency • Decimal.FormatStyle • Decimal.FormatStyle.Percent • Decimal.FormatStyle.Currency • PersonNameComponents.FormatStyle • URL.FormatStyle 150

Slide 151

Slide 151 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. FormatStyle Λࣗ࡞͢Δ 151

Slide 152

Slide 152 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 152 treastrain/XCIntelligenceBridge: https://github.com/treastrain/XCIntelligenceBridge

Slide 153

Slide 153 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 153

Slide 154

Slide 154 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. struct ContentView: View { @State private var port: NWEndpoint.Port = 8080 var body: some View { TextField( "Port", value: $port, format: ... ) } } 154 String NWEndpoint.Port

Slide 155

Slide 155 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 155 extension NWEndpoint.Port { struct FormatStyle: Foundation.FormatStyle { func format(_ value: NWEndpoint.Port) -> String { ... } } }

Slide 156

Slide 156 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 156 extension NWEndpoint.Port { struct FormatStyle: Foundation.FormatStyle { func format(_ value: NWEndpoint.Port) -> String { value.rawValue.formatted(.number.grouping(.never)) } } }

Slide 157

Slide 157 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 157 extension FormatStyle where Self == NWEndpoint.Port.FormatStyle { static var port: Self { .init() } } extension NWEndpoint.Port { func formatted() -> FormatStyle.FormatOutput { FormatStyle.port.format(self) } } NWEndpoint.Port(8080).formatted()

Slide 158

Slide 158 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 158 extension NWEndpoint.Port { struct FormatStyle: Foundation.FormatStyle { func format(_ value: NWEndpoint.Port) -> String { ... } } }

Slide 159

Slide 159 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 159 extension NWEndpoint.Port { struct FormatStyle: ParseableFormatStyle { let parseStrategy: ParseStrategy func format(_ value: NWEndpoint.Port) -> String { ... } } }

Slide 160

Slide 160 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 160 extension NWEndpoint.Port { struct FormatStyle: ParseableFormatStyle { ... } struct ParseStrategy: Foundation.ParseStrategy { func parse(_ value: String) throws -> NWEndpoint.Port { if let port = NWEndpoint.Port(value) { return port } else { throw CocoaError(.formatting, ...) } } } }

Slide 161

Slide 161 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. 161 extension ParseableFormatStyle where Self == NWEndpoint.Port.FormatStyle { static var port: Self { .init(parseStrategy: .port) } } extension ParseStrategy where Self == NWEndpoint.Port.ParseStrategy { static var port: Self { .init() } } extension NWEndpoint.Port { func formatted() -> FormatStyle.FormatOutput { FormatStyle.port.format(self) } } NWEndpoint.Port(8080).formatted()

Slide 162

Slide 162 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ͦΖͦΖ FormatStyle • ʮσʔλͷϑΥʔϚοτʯ͸ීஈͷ։ൃͷதʹᷓΕ͍ͯΔ • ͸͡Ί͔Β༻ҙ͞Ε͍ͯΔ FormatStyle ͸๛෋ʹ͋Γɺ Swift Β͍҆͠શ͞΍ SwiftUI ͷΑ͏ͳΠϯλʔϑΣΠεΛඋ͍͑ͯΔ • ಠࣗͷ FormatStyle Λ࡞֦ͬͯுͰ͖Δॊೈ͕͋͞Δ 162

Slide 163

Slide 163 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. ؔ࿈ • ຊτʔΫͷλΠτϧ͸ iOSDC Japan 2020 ͷ shiz ͞ΜͷτʔΫʮͦΖͦΖ CombineʯͷΦϚʔδϡͰ͢ • Foundationͷ৽ػೳ - WWDC21 - ϏσΦ - Apple Developer https://developer.apple.com/jp/videos/play/wwdc2021/10109/ • Get it right (to left)ʢӈ͔Βࠨํ޲΁ͷจࣈମʣ - WWDC22 - ϏσΦ - Apple Developer https://developer.apple.com/jp/videos/play/wwdc2022/10107/ • ΞϓϦͷଟݴޠମݧͷ޲্ - WWDC25 - ϏσΦ - Apple Developer https://developer.apple.com/jp/videos/play/wwdc2025/222/ • InstrumentsʹΑΔSwiftUIͷύϑΥʔϚϯε࠷దԽ - WWDC25 - ϏσΦ - Apple Developer https://developer.apple.com/jp/videos/play/wwdc2025/306/ 163

Slide 164

Slide 164 text

Copyright © 2025 treastrain / Tanaka RyogaɹAll rights reserved. #iosdc #b 164 #iosdc #b iOSDC Japan 2025 Day 1 ͦΖͦΖ FormatStyle Happy formatting!ɹɹɹɹɹɹɹɹ ɹࢿྉ͸ tret.jp ʹܝࡌ ⏩