Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOSDC 2024

iOSDC 2024

Mike Apurin

August 22, 2024
Tweet

More Decks by Mike Apurin

Other Decks in Programming

Transcript

  1. ७ਖ਼όοΫϙʔτ / σϑΥϧτҾ਺͕มΘΔ • SwiftͰ͸ɺσϑΥϧτҾ਺͕ϑϨʔϜϫʔΫͷόΠφϦʹ૊Έࠐ·Εͣ swiftinterfaceʹଘࡏ͍ͯ͠Δ @frozen public struct RoundedRectangle

    : SwiftUI.Shape { @inlinable public init( cornerRadius: CoreFoundation.CGFloat, style: SwiftUI.RoundedCornerStyle = .circular ) { // ... } } @frozen public struct RoundedRectangle : SwiftUICore.Shape { @inlinable nonisolated public init( cornerSize: CoreFoundation.CGSize, style: SwiftUICore.RoundedCornerStyle = .continuous ) { // ... }
  2. ७ਖ਼όοΫϙʔτ / ࣮૷͕·Δ͝ͱswiftinterfaceʹల։͞ΕΔ • ؔ਺Λ @inlinable ΍ @_alwaysEmitIntoClient Ͱम০͢Δͱɺ࣮૷͕ϑϨʔϜϫʔ ΫͷόΠφϦʹ૊Έࠐ·Εͣ

    swiftinterface ʹιʔείʔυͷ··Ͱίϐʔ͞ΕΔ • όοΫϙʔτʹݶΒͣ SwiftUI Ͱͦͷύλʔϯ͕ଟ͘࢖ΘΕ͍ͯΔ extension SwiftUICore.Shape where Self == SwiftUICore.RoundedRectangle { @_alwaysEmitIntoClient public static func rect( cornerSize: CoreFoundation.CGSize, style: SwiftUICore.RoundedCornerStyle = .continuous ) -> Self { .init( cornerSize: cornerSize, style: style ) } }
  3. ७ਖ਼όοΫϙʔτ / iOS 18 nonisolated public func onGeometryChange<T>( for type:

    T.Type, of transform: @escaping (GeometryProxy) -> T, action: @escaping (_ newValue: T) -> Void ) -> some View where T : Equatable nonisolated public func gesture<T>( _ gesture: T, isEnabled: Bool ) -> some View where T : Gesture nonisolated public func tag<V>( _ tag: V, includeOptional: Bool = true ) -> some View where V : Hashable
  4. ७ਖ਼όοΫϙʔτ / ݹ͍OS͚ͩswiftinterfaceʹ࣮૷͕ల։͞ΕΔ • ݹ͍OSͰγϯϘϧ͕ଘࡏ͍ͯ͜͠ͱʹ͢ΔͨΊͷम০: @backDeployed • ৽OS͸ϥΠϒϥϦͷόΠφϦΛ࢖͍ͭͭɺݹ͍OS͸swiftinterfaceͷ࣮૷Λ࢖͏͜ͱͱ͔ • SwiftUIʹ͸΄ͱΜͲݟͳ͍͕ɺStoreKitͰ͸ಛʹΑ͘࢖ΘΕ͍ͯΔ

    struct Transaction { @backDeployed(before: iOS 17.2, macOS 14.2, tvOS 17.2, watchOS 10.2, visionOS 1.1) public var currency: Foundation.Locale.Currency? { get { if #available(iOS 17.2, macOS 14.2, tvOS 17.2, watchOS 10.2, visionOS 1.1, *) { return currencyStorage } else { return backing.value( atKeyPath: "currency", sentinel: nil, transform: { String($0).map({ Locale.Currency($0) }) } ) } } } }
  5. ϚΫϩ / Xcode 16 struct MyCustomValueKey: EnvironmentKey { static var

    defaultValue: String { "Default value" } } extension EnvironmentValues { var myCustomValue: String { get { self[MyCustomValueKey.self] } set { self[MyCustomValueKey.self] = newValue} } } extension EnvironmentValues { @Entry var myCustomValue: String = "Default value" }
  6. ϚΫϩ / Xcode 16 private struct PreviewContent: View { @State

    var toggled = true var body: some View { Toggle("Loud Noises", isOn: $toggled) } } #Preview("toggle") { PreviewContent() } #Preview("toggle") { @Previewable @State var toggled = true return Toggle("Loud Noises", isOn: $toggled) }
  7. OSSͷόοΫϙʔτ / SwiftUI৭ʑ • ͋Ε΍͜Εͷ SwiftUI ػೳͷόοΫϙʔτ • StateObject •

    AppStorage • AsyncImage • .task • ͳͲͳͲ shaps80/SwiftUIBackports
  8. OSSͷόοΫϙʔτ / Group(subviews:transform:) • iOS 18Ͱ৽͘͠௥Ճ͞Εͨ Group ͷػೳ • GroupͷதͷࢠϏϡʔͰԿΒ͔ͷॲཧΛ͢Δ

    • iOS 17ҎԼͰ͸ඇެ։ͷVariadicViewΛ࢖͏ඞ ཁ͕͋ͬͨ Lumisilk/SwiftUI-AnySubviews
  9. ʮόοΫϙʔτʯ͔ʮϑΥʔϧόοΫʯ͔ @ViewBuilder var unavailableView: some View { if #available(iOS 17,

    *) { // ... } else { VStack(spacing: 16) { Image(systemName: "magnifyingglass") .font(.system(.largeTitle).weight(.medium)) .imageScale(.large) .foregroundColor(.secondary) VStack { Text("ݕࡧ݁Ռ͕͋Γ·ͤΜ") .font(.title2.bold()) Text("ผͷΩʔϫʔυΛ͓ࢼ͍ͩ͘͠͞") .font(.callout) .foregroundColor(.secondary) } } } }
  10. όοΫϙʔτΛ࣮૷ / ద੾ͳωʔϛϯά • ޙ΄Ͳ࡟আ͞ΕΔલఏͷίʔυ • Ͳ͜Ͱ࢖ΘΕ͍ͯΔ͔ɺͲ͏΍ͬͯണ͕͢ͷ͔Λ࣮૷౰͔࣌ΒܾΊΔ • enum Backport

    ͰωʔϜεϖʔεΛ࡞͓ͬͯ͘ͱศར • ݩωλ͸ Dave DeLong ࢯͷهࣄ • https://davedelong.com/blog/2021/10/09/simplifying-backwards-compatibility- in-swift/
  11. όοΫϙʔτΛ࣮૷ / ద੾ͳωʔϛϯά public struct Backport<Content> { public let content:

    Content public init(_ content: Content) { self.content = content } } extension View { var backport: Backport<Self> { Backport(self) } } extension Backport where Content: View { func myNewFunction() -> some View { // ... } } // ... Text("iOSDC 2024") .backport.myNewFunction()
  12. όοΫϙʔτΛ࣮૷ / geometryGroup struct ContentView: View { @State var flag

    = false @State var flag2 = false var body: some View { Color.cyan .frame(width: 128, height: 128) .overlay { Group { if flag2 { Text("iOSDC") } else { Text("લ໷ࡇ") } } .task(id: flag2) { try? await Task.sleep(for: .seconds(1.5)) flag2.toggle() } } .offset(y: flag ? 100 : -100) .animation(.linear(duration: 1).repeatForever(), value: flag) .onAppear() { flag.toggle() } } }
  13. όοΫϙʔτΛ࣮૷ / geometryGroup struct ContentView: View { @State var flag

    = false @State var flag2 = false var body: some View { Color.cyan .frame(width: 128, height: 128) .overlay { Group { if flag2 { Text("iOSDC") } else { Text("લ໷ࡇ") } } .task(id: flag2) { try? await Task.sleep(for: .seconds(1.5)) flag2.toggle() } } .geometryGroup() .offset(y: flag ? 100 : -100) .animation(.linear(duration: 1).repeatForever(), value: flag) .onAppear() { flag.toggle() } } }
  14. όοΫϙʔτΛ࣮૷ / geometryGroup • geometryGroup͸iOS 17Ҏ߱ 😇 • ͨͩ͠ɺ࣮͸ผͷॻ͖ํͰಉ༷ͳޮՌ͕ಘΒΕΔ extension

    Backport where Content: View { @ViewBuilder func geometryGroup() -> some View { if #available(iOS 17, *) { content.geometryGroup() } else { content.transformEffect(.identity) } } } // ... } .backport.geometryGroup() .offset(y: flag ? 100 : -100) // ...